/* ============ FogiDesk · the two typefaces, served from this host ============
 *
 * ⚠️ THESE USED TO COME FROM fonts.googleapis.com AND fonts.gstatic.com, WHICH
 *    MEANT EVERY PAGE LOAD TOLD GOOGLE THE READER'S IP ADDRESS.
 *
 * Not a performance note. FogiDesk is the processor for a Danish tenant's case
 * content and the sub-processor list does not name Google, so a font request on
 * every page was a third-party data flow the paperwork did not describe. Self
 * hosting removes it rather than documenting it, which is the cheaper of the
 * two fixes and the better one.
 *
 * It also removes two allowances from the Content-Security-Policy —
 * `style-src https://fonts.googleapis.com` and `font-src https://fonts.gstatic.com`
 * — so the policy is now `'self'` for both. A stylesheet from anywhere else is
 * refused by the browser instead of being trusted because the fonts needed it.
 *
 * Both families are variable and SIL OFL 1.1; the licences ship beside them in
 * fonts/. Latin and latin-ext only: this product is Danish and English, and the
 * cyrillic, greek and vietnamese subsets Google also serves would be 200 KB
 * nobody ever renders. The unicode-range on each face is Google's own, so a
 * character outside latin still falls through to the next family in the stack
 * rather than to a box.
 *
 * font-display: swap, deliberately. Text drawn in the fallback and then
 * corrected is worse-looking than text that appears late, and better than a
 * screen that shows nothing while a font loads.
 */
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('fonts/inter-latin.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('fonts/inter-latin-ext.woff2?v=1') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'Schibsted Grotesk';font-style:normal;font-weight:400 900;font-display:swap;
  src:url('fonts/schibsted-latin.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'Schibsted Grotesk';font-style:normal;font-weight:400 900;font-display:swap;
  src:url('fonts/schibsted-latin-ext.woff2?v=1') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ⚠️ DM MONO IS HERE AND NOT IN operator.css ON PURPOSE. Only the operator
 * console names it (`--op-mono`), and operator.html loads BOTH stylesheets — so
 * declaring it there would have worked, and would have left one page still
 * asking Google for a font while every other page had stopped. One place to
 * look, one place to be wrong. It is a static family rather than variable, so
 * the two weights operator.css actually uses are two faces; nothing asks for a
 * third.
 */
@font-face{
  font-family:'DM Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/dmmono-400-latin.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'DM Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('fonts/dmmono-400-latin-ext.woff2?v=1') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face{
  font-family:'DM Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url('fonts/dmmono-500-latin.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:'DM Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url('fonts/dmmono-500-latin-ext.woff2?v=1') format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============ FogiDesk · full prototype · v1 design system ============ */
:root{
  --brand:#0E4A8C;
  --brand-600:#0C3F77;
  --brand-700:#0A3462;
  --brand-100:#DCE8F6;
  --brand-50:#EFF4FB;
  /* Brand-coloured TEXT (a link). The brand itself on a light card; lifted
     on the dark one, see html.dark. */
  --link:var(--brand);
  --ink:#0F1522;
  --text:#1C2433;
  --text-2:#5A6474;
  --text-3:#666D7D; /* audit: #939CAB -> #7C8494 -> her. Se noten nedenfor. */
  --bg:#F4F5F7;
  --card:#FFFFFF;
  --border:#E6E9EF;
  --border-2:#EEF0F4;

  --green:#15803D;   --green-dot:#22A55E;  --green-bg:#E9F6EF;  --green-br:#CBE9D8;
  --amber:#A16003;   --amber-dot:#EFA00B;  --amber-bg:#FCF3E1;  --amber-br:#F3E1BB;
  --red:#BE2D20;     --red-dot:#E2483A;    --red-bg:#FCEDEA;    --red-br:#F5D2CC;

  --shadow-sm: 0 1px 2px rgba(15,21,34,.05);
  --shadow-md: 0 1px 2px rgba(15,21,34,.05), 0 10px 30px -14px rgba(15,21,34,.16);
  --shadow-lg: 0 2px 4px rgba(15,21,34,.06), 0 24px 60px -24px rgba(15,21,34,.24);

  --r-lg:16px; --r-md:12px; --r-sm:9px;
  --font-ui:"Inter",-apple-system,system-ui,sans-serif;
  --font-display:"Schibsted Grotesk",var(--font-ui);
}

/* ⚠️ --text-3 WAS LIFTED TWICE AND STILL DID NOT PASS.
 *
 * #939CAB, then #7C8494 under an audit whose note says "for WCAG-kontrast på
 * hvid" — and on white it reached 3.76:1, on --bg 3.45:1. AA wants 4.5:1 for
 * text under 18.66px, and every single thing wearing this token is small: the
 * nav labels at 10.5px, the sidebar user at 11.5px, the route line at 11px.
 * The measurement was taken against the wrong background and against the wrong
 * threshold, so a fix that felt done was 24% short of its own goal.
 *
 * #666D7D is 4.75:1 on --bg and 5.19:1 on --card, same hue and saturation, and
 * still clearly a step lighter than --text-2 (5.48:1), so the three-step ramp
 * this palette is built on survives. Dark mode already passed at 5.71 to 6.22
 * and is untouched.
 *
 * check.php parses these tokens and measures them, both themes, both
 * backgrounds. A future nudge that drops one under 4.5 fails the build rather
 * than shipping, which is what the two previous lifts needed and did not have.
 */
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
body{
  font-family:var(--font-ui);
  font-size:14px; line-height:1.5;
  color:var(--text);
  background:var(--bg);
  overflow-x:hidden;
  /* ⚠️ A WORD NEVER PAINTS OUTSIDE THE BOX THAT HOLDS IT.
     People paste links. One address of 300 characters in a title, a message or
     a note has no place to break, so it ran straight out of its bubble, its
     list cell and its card, and the page behind it grew to thousands of pixels
     with the action cards far off screen, for everyone who opened that case.
     break-word, not anywhere: it breaks a word only where the line would
     otherwise overflow and leaves min-content sizes alone, so a label in a
     flex row is never squeezed to one letter per line. The other half of the
     rule is the track: a column that takes free text is minmax(0,1fr) or has
     min-width:0, because a bare 1fr or an auto flex item refuses to be
     narrower than its longest word however the word is allowed to break. */
  overflow-wrap:break-word;
}
button{font:inherit;cursor:pointer;border:none;background:none;color:inherit}
input,textarea,select{font:inherit;color:inherit}
::selection{background:var(--brand-100)}
:focus-visible{outline:2px solid rgba(14,74,140,.45);outline-offset:2px;border-radius:6px}

/* ============ Shell ============ */
.shell{display:flex;min-height:100vh}
.side{
  width:242px; flex-shrink:0;
  background:#FBFBFC;
  border-right:1px solid var(--border);
  display:flex;flex-direction:column;
  position:sticky;top:0;height:100vh;
  padding:18px 12px 14px;
}
.side-logo{display:flex;align-items:center;gap:11px;padding:2px 8px 16px}
.side-logo>img{width:38px;height:38px;object-fit:contain;flex:0 0 38px}
/* The square in the corner. Its gradient was two more hardcoded blues, so a
   workspace that had chosen its own colour still had somebody else's mark at
   the top of every screen. Derived now, like everything else that carries the
   brand. */
.logo-mark{
  width:38px;height:38px;border-radius:11px;flex-shrink:0;
  background:linear-gradient(145deg,var(--brand), var(--brand-700));
  color:#fff;display:grid;place-items:center;
  font-family:var(--font-display);font-weight:800;font-size:15px;letter-spacing:-.02em;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22), 0 2px 6px -2px rgba(15,21,34,.34);
  overflow:hidden;
}
/* A published logo replaces the gradient rather than sitting on it: a mark
   drawn for white paper on a coloured square is the wrong mark. */
.logo-mark.haslogo{background:#fff;box-shadow:inset 0 0 0 1px var(--border)}
.logo-mark img{width:78%;height:78%;object-fit:contain;display:block}
.logo-txt b{display:block;font-family:var(--font-display);font-weight:700;font-size:15px;letter-spacing:-.01em;color:var(--ink)}
.logo-txt span{font-size:11.5px;color:var(--text-3);font-weight:500;letter-spacing:.01em}
.side-nav{flex:1;min-height:0;overflow-y:auto;margin:0 -4px;padding:0 4px}
.nav-group{margin-top:14px}
.nav-label{font-size:10.5px;font-weight:650;letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:0 10px 6px}
.nav-item{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:8px 10px;border-radius:10px;
  font-size:13.5px;font-weight:500;color:var(--text-2);
  transition:background .15s ease,color .15s ease;
  position:relative;text-align:left;
}
.nav-item svg{width:18px;height:18px;flex-shrink:0;opacity:.75;transition:opacity .15s}
.nav-item:hover{background:#F1F2F5;color:var(--ink)}
.nav-item:hover svg{opacity:1}
.nav-item.active{background:var(--brand-50);color:var(--brand);font-weight:600}
.nav-item.active svg{opacity:1}
.nav-item.active::before{
  content:"";position:absolute;left:-12px;top:7px;bottom:7px;width:3px;
  background:var(--brand);border-radius:0 3px 3px 0;
}
.nav-badge{
  margin-left:auto;min-width:20px;height:20px;padding:0 6px;border-radius:999px;
  background:var(--amber-dot);color:#fff;font-size:11px;font-weight:700;
  display:grid;place-items:center;
  transition:transform .3s cubic-bezier(.34,1.56,.64,1);
}
.nav-badge.zero{background:var(--border);color:var(--text-3)}
.nav-cnt{margin-left:auto;font-size:11.5px;color:var(--text-3)}
.side-foot{margin-top:auto;padding-top:12px}
.side-user{
  display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:12px;
  transition:background .15s;cursor:pointer;
}
.side-user:hover{background:#F1F2F5}
.side-user .avatar{width:32px;height:32px;font-size:12px}
.side-user b{display:block;font-size:13px;font-weight:600;color:var(--ink);line-height:1.25}
.side-user span{font-size:11.5px;color:var(--text-3)}
.powered{
  display:flex;align-items:center;gap:7px;
  padding:12px 10px 2px;margin-top:6px;border-top:1px solid var(--border-2);
  font-size:11px;color:var(--text-3);font-weight:500;letter-spacing:.01em;
}
.powered i{width:8px;height:8px;border-radius:3px;background:#104925;display:inline-block}
/* The operating firm's own mark, in place of the dot. Bounded on both axes and
   `contain`, because this is somebody else's artwork at a size we do not
   control: a tall logo must not push the sidebar footer open, and a wide one
   must not crop to nonsense. */
.powered-mark{width:16px;height:16px;object-fit:contain;flex-shrink:0;border-radius:3px}

/* --- Topbar --- */
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{
  height:60px;flex-shrink:0;
  display:flex;align-items:center;gap:12px;
  padding:0 26px;
  background:rgba(244,245,247,.86);
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--border-2);
  position:sticky;top:0;z-index:40;
}
.search{
  display:flex;align-items:center;gap:9px;
  width:340px;height:38px;padding:0 13px;
  background:var(--card);border:1px solid var(--border);border-radius:11px;
  color:var(--text-3);
  transition:box-shadow .18s,border-color .18s,background .15s;
  cursor:pointer;text-align:left;
}
.search:hover{border-color:#CBD6E4;background:#FDFDFE}
/* The magnifier never gives way. On a phone the pill is squeezed to about
   40px and the flex algorithm took the width from the icon first, so every
   console showed a blank white box where search is (wave 2 walk D2). */
.search svg{flex-shrink:0}
/* One line, cut with an ellipsis where the box is short: between 921 and
   1180px the box is 220px, and "Søg i sager, leverandører og butikker" stood
   on three lines, the first and the last outside the box. */
.search .ph{flex:1;min-width:0;font-size:13.5px;color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* And no words at all where there is not room for a few. On a phone the box
   takes what the top bar has left: 40px beside "Ny sag", where the words had
   no room and did not show, and some 60px for a reader, who has no such
   button and read "S…". With less than 96px inside it (the magnifier and ten
   letters) the box is its magnifier, in the middle of it; from there up it
   says at least "Søg i sager…". Asked of the box itself, since its width
   follows from what else is in the bar, not from the window. */
.search{container-type:inline-size}
@container (max-width:95px){
  .search .ph{display:none}
  .search svg{margin:0 auto}
}
.search kbd{
  font-family:var(--font-ui);font-size:10.5px;color:var(--text-3);
  border:1px solid var(--border);border-bottom-width:2px;border-radius:5px;padding:1px 5px;background:#FAFAFB;
}
.topbar .grow{flex:1}
.icon-btn{
  width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  color:var(--text-2);border:1px solid transparent;position:relative;
  transition:background .15s,border-color .15s,color .15s;
}
.icon-btn:hover{background:var(--card);border-color:var(--border);color:var(--ink)}
#langBtn{
  width:56px;padding:0 6px;cursor:pointer;
  background:transparent;font:700 11px/1 var(--font-ui);letter-spacing:.02em;
}
#langBtn:hover{background:var(--card)}
.icon-btn .dot{
  position:absolute;top:9px;right:10px;width:7px;height:7px;border-radius:50%;
  background:var(--red-dot);border:1.5px solid var(--bg);
}
.avatar{
  width:34px;height:34px;border-radius:50%;
  background:linear-gradient(145deg,#3D6FB0,#0E4A8C);
  color:#fff;font-size:12px;font-weight:650;
  display:grid;place-items:center;letter-spacing:.02em;flex-shrink:0;
}
.avatar.mk{background:linear-gradient(145deg,#2B8A5C,#104925)}
.avatar.jf{background:linear-gradient(145deg,#8A6ED1,#5B3FA8)}
.avatar.mh{background:linear-gradient(145deg,#C2703E,#8F4A1E)}
.avatar.ld{background:linear-gradient(145deg,#4A7B9D,#2C5670)}
.avatar.sys{background:#EDF0F4;color:var(--text-3)}

/* ============ Buttons & chips ============ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:38px;padding:0 16px;border-radius:11px;
  font-size:13.5px;font-weight:600;letter-spacing:.005em;
  transition:transform .16s ease,box-shadow .16s ease,background .16s ease,border-color .16s,color .16s,opacity .2s;
  white-space:nowrap;
}
.btn:active{transform:translateY(0) scale(.98)}
.btn svg{width:15px;height:15px;flex-shrink:0}
.btn.sm svg{width:13px;height:13px}
.btn-primary{
  background:var(--brand);color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14), 0 1px 2px rgba(10,52,98,.3), 0 6px 16px -8px rgba(10,52,98,.5);
}
.btn-primary:hover{background:var(--brand-600);transform:translateY(-1px);box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 2px 4px rgba(10,52,98,.28),0 10px 22px -8px rgba(10,52,98,.55)}
.btn-ghost{background:var(--card);border:1px solid var(--border);color:var(--text);box-shadow:var(--shadow-sm)}
.btn-ghost:hover{border-color:#D5DAE2;background:#FCFCFD;transform:translateY(-1px);box-shadow:var(--shadow-md)}
.btn-danger{background:var(--card);border:1px solid var(--border);color:var(--red);box-shadow:var(--shadow-sm)}
.btn-danger:hover{border-color:var(--red-br);background:var(--red-bg);transform:translateY(-1px)}
.btn-success{background:var(--green);color:#fff;pointer-events:none}
.btn[disabled]{opacity:.55;pointer-events:none}
.btn.sm{height:32px;padding:0 13px;font-size:12.5px;border-radius:9px}
/* A button whose label is a list of names ("Kræv det for El og lys, Vand og
   afløb, ...") wraps instead of pushing the page 160px wider than a phone. */
.btn.wraps{height:auto;min-height:32px;padding-top:6px;padding-bottom:6px;white-space:normal;text-align:left;line-height:1.35}
.btn .spin{
  width:15px;height:15px;border-radius:50%;
  border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

.chip{
  display:inline-flex;align-items:center;gap:6px;
  height:24px;padding:0 10px;border-radius:999px;
  font-size:11.5px;font-weight:650;letter-spacing:.01em;white-space:nowrap;
  /* ⚠️ A CHIP NEVER PAINTS OUTSIDE WHAT HOLDS IT.
     white-space:nowrap plus a fixed grid column and no bound is how "Open ·
     awaiting assignment" — 193px of it — came to sit across the priority in a
     168px cell on every case list. The label is its own element so it can
     ellipsis (a bare text node cannot), and the full wording stays in the
     title attribute. The columns are sized so this is a backstop rather than
     the normal case.

     ⚠️ overflow:hidden BELONGS ON THE CHIP AS WELL AS ON THE LABEL, and for a
     different reason. Roughly ninety chips across the consoles are written
     inline — an invoice state, a plan, a tender — and carry a bare text node
     rather than a label element. max-width alone would clamp the pill and let
     the text keep painting past the end of its own background, which reads
     worse than the overlap being fixed here. This clips those; the ones built
     by statusChip get a proper ellipsis from the rule below. */
  max-width:100%;overflow:hidden;
}
.chip i{width:7px;height:7px;border-radius:50%;flex-shrink:0}
.chip-label{overflow:hidden;text-overflow:ellipsis;min-width:0}
/* A status that is a sentence ("Meldt udført · afventer kontrol"): where its
   column cannot hold it on one line the pill takes two, instead of being cut
   in the middle of the words that say what to do. */
.chip.wraps{white-space:normal;height:auto;min-height:24px;padding:3px 10px;line-height:1.3;border-radius:12px}
/* What a person wrote on a case, read on its page: the title, the report,
   each message and the lines the system adds from them (an access note). A
   pasted address has nowhere to break, so one of them made the supplier's
   job page 2700px wide on a phone and stretched the column on a desk. */
.case-head h1,.bubble,.sysline{overflow-wrap:anywhere}
.chip.green{background:var(--green-bg);color:var(--green);border:1px solid var(--green-br)}
.chip.green i{background:var(--green-dot)}
.chip.amber{background:var(--amber-bg);color:var(--amber);border:1px solid var(--amber-br)}
.chip.amber i{background:var(--amber-dot)}
.chip.red{background:var(--red-bg);color:var(--red);border:1px solid var(--red-br)}
.chip.red i{background:var(--red-dot)}
.chip.blue{background:var(--brand-50);color:var(--brand);border:1px solid var(--brand-100)}
.chip.blue i{background:var(--brand)}
.chip.gray{background:#F2F3F6;color:var(--text-2);border:1px solid var(--border)}
.chip.gray i{background:var(--text-3)}

/* The rest of a list. Sits under the rows, so it reads as part of the table
   rather than as a control bar floating above it. */
.list-more{display:flex;align-items:center;justify-content:center;gap:12px;
  padding:14px 16px;border-top:1px solid var(--border-2);
  font-size:12.5px;color:var(--text-3)}
.list-more button{font-size:12.5px;padding:6px 14px}

/* ============ Content ============ */
.content{padding:26px 26px 60px;max-width:1420px;width:100%;margin:0 auto}
.view{animation:viewIn .4s cubic-bezier(.22,.9,.3,1) both}
@keyframes viewIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes cardIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.rise{animation:cardIn .5s cubic-bezier(.22,.9,.3,1) both;animation-delay:calc(var(--i,0)*26ms)}

.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:20px;flex-wrap:wrap}
.page-head h1{
  font-family:var(--font-display);font-size:26px;font-weight:750;letter-spacing:-.025em;color:var(--ink);
  line-height:1.15;
}
.page-head .sub{margin-top:5px;font-size:13.5px;color:var(--text-2)}
.sub .g{color:var(--green);font-weight:600}
.sub .a{color:var(--amber);font-weight:600}
.sub .r{color:var(--red);font-weight:600}
.page-head .actions{display:flex;gap:9px;align-items:center}
.live{
  display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--text-3);font-weight:500;
}
.live i{
  width:8px;height:8px;border-radius:50%;background:var(--green-dot);position:relative;
}
.live i::after{
  content:"";position:absolute;inset:-3px;border-radius:50%;
  border:2px solid rgba(34,165,94,.4);animation:pulse 2.2s ease-out infinite;
}
@keyframes pulse{0%{transform:scale(.6);opacity:1}70%{transform:scale(1.4);opacity:0}100%{opacity:0}}

/* KPI */
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:22px}
/* Five figures in one row (Insight's headline since WP31 added "Came back"). */
.kpis.k5{grid-template-columns:repeat(5,1fr)}
/* Two or three, for a reader given fewer (M-02: no invoice figures without
   the right to read invoices): a row of their own, not four with a hole. */
.kpis.k2{grid-template-columns:repeat(2,1fr)}
.kpis.k3{grid-template-columns:repeat(3,1fr)}
.kpi{
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:16px 18px 15px;box-shadow:var(--shadow-sm);
  transition:transform .2s ease,box-shadow .2s ease;position:relative;overflow:hidden;
}
.kpi:hover{transform:translateY(-2px);box-shadow:var(--shadow-md)}
.kpi .lbl{font-size:12px;font-weight:600;color:var(--text-2);display:flex;align-items:center;gap:7px}
.kpi .lbl i{width:8px;height:8px;border-radius:50%}
/* ⚠️ PROPORTIONAL FIGURES IN THE DISPLAY FACE, ON EVERY TILE (B-08). The
   display face draws a tabular full stop and comma a whole figure wide, so
   a sum on a tile read "200 . 000 kr ." and "420 , 000 DKK". The offer's
   total was put right for it long ago (.oline.total .p); the tiles kept
   tabular-nums. A tile holds one figure and lines up with nothing, so it
   loses nothing by it: here, and on every other figure set in this face
   (.act-n, .appr-card .amt, .cstat b, .stat-tile .st-v, .finkpi .fk .v). */
.kpi .val{
  font-family:var(--font-display);font-size:32px;font-weight:800;letter-spacing:-.03em;color:var(--ink);
  margin-top:6px;line-height:1;font-variant-numeric:normal;
}
.kpi .val small{font-size:15px;font-weight:600;color:var(--text-3);letter-spacing:0}
/* ⚠️ AN AMOUNT AND ITS UNIT STAY ON ONE LINE, AND THE FIGURE SHRINKS TO FIT
   (W-04). "122.164,50 kr." is wider than a tile at this size. It used to run
   out past the tile's edge; since <body> breaks a word that has no room, it
   stood as "122.164,50 k" over "r.". A tile that holds a sum says how many
   characters it is (--len, where it is drawn) and the figure is as large as
   that many characters allow in the tile's own width, never larger than the
   figures beside it. .61 of the type size is the widest a character of a
   sum comes to, measured: "DKK 91,001.50" and "€1,234,567.50" in English;
   Danish kroner are .57.
   And a word in a tile is never cut in two: "Hovedkonto" over "r". */
.kpi .val{overflow-wrap:normal}
.kpi:has(> .val.sum){container-type:inline-size}
.kpi .val.sum{white-space:nowrap;font-size:min(var(--max,32px),calc(100cqi / (var(--len,8) * .61)))}
.kpi .foot{margin-top:8px;font-size:12px;color:var(--text-3)}
.kpi.k-green .lbl i{background:var(--green-dot)} .kpi.k-green .val{color:var(--green)}
.kpi.k-amber .lbl i{background:var(--amber-dot)} .kpi.k-amber .val{color:#B26205}
.kpi.k-red{border-color:var(--red-br);background:linear-gradient(180deg,#FFF, #FFF9F8)}
.kpi.k-red .lbl i{background:var(--red-dot)} .kpi.k-red .val{color:var(--red)}
.kpi.k-red::after{
  content:"";position:absolute;inset:0;border-radius:var(--r-lg);pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(226,72,58,.16);
}

/* Overview grid */
.ov-grid{display:grid;grid-template-columns:1fr 342px;gap:16px;align-items:start}
/* Three in a row (.kpis.k3, M-02) is two from here as four and five are: at
   three, "Ikke angivet" in the third ran into the tile's padding from 641 to
   721px and again from 921 to 990px, beside the menu. */
@media (max-width:1180px){.ov-grid{grid-template-columns:minmax(0,1fr)}.kpis,.kpis.k3,.kpis.k5{grid-template-columns:repeat(2,1fr)}.search{width:220px}}
.panel{
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);
}
.panel-h{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:16px 18px 0;flex-wrap:wrap}
.panel-h h2{font-family:var(--font-display);font-size:16px;font-weight:700;letter-spacing:-.015em;color:var(--ink)}
.panel-h .hint{font-size:12.5px;color:var(--text-3);margin-top:2px}
.panel-h .r{display:flex;gap:8px;align-items:center}

.pills{display:flex;gap:6px;flex-wrap:wrap;padding:14px 18px 4px}
.pills.bare{padding:0}
.pill{
  height:30px;padding:0 13px;border-radius:999px;
  border:1px solid var(--border);background:var(--card);
  font-size:12.5px;font-weight:600;color:var(--text-2);
  transition:all .16s ease;
}
.pill:hover{border-color:#CBD3DE;color:var(--ink)}
.pill.on{background:var(--ink);border-color:var(--ink);color:#fff}
.pill .n{opacity:.55;font-weight:600;margin-left:4px;font-variant-numeric:tabular-nums}

.stores{display:grid;grid-template-columns:repeat(auto-fill,minmax(172px,1fr));gap:10px;padding:14px 18px 18px}
.store{
  position:relative;text-align:left;
  border:1px solid var(--border);border-radius:13px;
  background:linear-gradient(180deg,#FDFDFE,#F8FAF9);
  padding:12px 13px 11px;min-height:96px;
  display:flex;flex-direction:column;
  border-left-width:3px;border-left-color:var(--green-dot);
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;
  cursor:pointer;
}
.store:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:#D8DDE5;border-left-color:var(--green-dot)}
.store .top{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.store .nm{font-size:12.5px;font-weight:700;color:var(--ink);line-height:1.25;letter-spacing:-.005em}
.store .st{font-size:11.5px;color:var(--text-2);margin-top:5px;line-height:1.35;overflow-wrap:anywhere}
.store .mt{margin-top:auto;padding-top:7px;font-size:10.5px;color:var(--text-3);display:flex;align-items:center;gap:5px}
.store .mt svg{width:11px;height:11px;opacity:0;transform:translateX(-3px);transition:all .18s ease}
.store:hover .mt svg{opacity:.8;transform:none}
.sdot{width:8px;height:8px;border-radius:50%;background:var(--green-dot);flex-shrink:0;margin-top:3px;position:relative}
.store.amber{background:linear-gradient(180deg,#FFFDF8,#FEF8EA);border-left-color:var(--amber-dot)}
.store.amber:hover{border-left-color:var(--amber-dot)}
.store.amber .sdot{background:var(--amber-dot)}
.store.amber .st{color:#8A5A10;font-weight:600}
.store.red{background:linear-gradient(180deg,#FFFBFA,#FDF0EE);border-left-color:var(--red-dot)}
.store.red:hover{border-left-color:var(--red-dot)}
.store.red .sdot{background:var(--red-dot)}
.store.red .sdot::after{
  content:"";position:absolute;inset:-4px;border-radius:50%;
  border:2px solid rgba(226,72,58,.4);animation:pulse 1.8s ease-out infinite;
}
.store.red .st{color:var(--red);font-weight:650}
.legend{
  display:flex;align-items:center;gap:18px;padding:0 18px 16px;
  font-size:12px;color:var(--text-2);flex-wrap:wrap;
}
.legend b{font-weight:600}
.legend .lg{display:inline-flex;align-items:center;gap:6px}
.legend .lg i{width:8px;height:8px;border-radius:50%}
.legend .right{margin-left:auto;color:var(--text-3)}

/* Grey and quiet (WP29). Grey is "we know nothing yet", drawn as the absence
   of a colour so it never reads as running; quiet is live but silent, the
   amber edge without the amber fill. */
.store.grey{background:linear-gradient(180deg,#FBFBFC,#F4F5F7);border-left-color:#C3C8D1}
.store.grey:hover{border-left-color:#C3C8D1}
.store.grey .sdot{background:#C3C8D1}
.store.grey .nm{color:var(--text-2)}
.store.grey .st{color:var(--text-3)}
.store.quiet{border-left-color:var(--amber-dot)}
.store.quiet:hover{border-left-color:var(--amber-dot)}
.store.quiet .sdot{background:transparent;box-shadow:inset 0 0 0 2px var(--amber-dot)}
.store.quiet .st{color:#8A5A10}
.legend .lg i.green{background:var(--green-dot)}
.legend .lg i.amber{background:var(--amber-dot)}
.legend .lg i.red{background:var(--red-dot)}
.legend .lg i.quiet{background:transparent;box-shadow:inset 0 0 0 2px var(--amber-dot)}
.legend .lg i.grey{background:#C3C8D1}
/* The stats panels' .legend further down is a column; the overview's is a row
   under the tiles, and it lost that fight on source order. */
.legend.tl-legend{flex-direction:row;align-items:center;gap:8px 18px;padding:0 18px 16px;flex:none;min-width:0}
.kpi.k-grey .lbl i{background:#C3C8D1}
.kpi.k-grey .val{color:var(--text-2)}
button.kpi{font:inherit;color:inherit;text-align:left;width:100%;cursor:pointer}

/* Right rail */
.rail{display:flex;flex-direction:column;gap:14px}
.act-list{padding:6px 8px 8px}
/* ⚠️ UNDER .act-list, NOT BARE (WP31). A bare .act also matched the
   filter row's active state (.fsel.act, .fchip.act), so every chosen filter
   in every console took this width:100% and padding and broke the row onto
   lines of its own. Both action rails sit inside .act-list. */
/* minmax(0,1fr): a bare 1fr is never narrower than its longest word, and a
   case titled with one long word (a link, a part number) pushed the whole
   overview 496px sideways on a phone, and 116px at 1024. */
.act-list .act{
  display:grid;grid-template-columns:10px minmax(0,1fr) auto;gap:11px;align-items:start;
  padding:11px 10px;border-radius:11px;cursor:pointer;text-align:left;width:100%;
  transition:background .15s;
}
.act-list .act:hover{background:#F6F7F9}
.act-list .act + .act{border-top:1px solid var(--border-2)}
.act-list .act .adot{width:8px;height:8px;border-radius:50%;margin-top:5px}
.act-list .act .adot.red{background:var(--red-dot)}
.act-list .act .adot.amber{background:var(--amber-dot)}
.act-list .act .adot.gray{background:#C3C8D1}
.act-list .act.act-line{align-items:center}
.act-list .act.act-line .adot{margin-top:0}
.act-list .act .act-n{font-family:var(--font-display);font-size:15px;font-weight:800;color:var(--ink);font-variant-numeric:normal}
.act-list .act.zero b{color:var(--text-2);font-weight:600}
.act-list .act.zero .act-n{color:var(--text-3)}
.bline-left{font-size:11px;color:var(--text-3);text-align:right;margin:-3px 0 6px}
.bline-left.over{color:var(--red);font-weight:650}
.act-list .act b{font-size:12.5px;font-weight:700;color:var(--ink);display:block}
.act-list .act .is{display:block;font-size:12px;color:var(--text-2);margin-top:1px;line-height:1.35}
.act-list .act .ms{display:block;font-size:10.5px;color:var(--text-3);margin-top:3px}
.tag{
  font-size:9.5px;font-weight:750;letter-spacing:.05em;text-transform:uppercase;
  padding:3px 7px;border-radius:6px;white-space:nowrap;
}
.tag.akut{background:var(--red-dot);color:#fff}
.tag.hoj{background:#FBE4DA;color:#B82800}
.tag.med{background:#FEF3C7;color:#B45309}
.tag.lav{background:#F2F3F6;color:var(--text-2)}

.appr-card{
  border:1px solid var(--amber-br);
  background:linear-gradient(180deg,#FFFDF6,#FDF6E6);
  border-radius:var(--r-lg);padding:16px;box-shadow:var(--shadow-sm);
  cursor:pointer;transition:transform .18s,box-shadow .18s;text-align:left;width:100%;
}
.appr-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md)}
.appr-card .ttl{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--amber)}
.appr-card .ttl svg{width:15px;height:15px}
.appr-card .amt{font-family:var(--font-display);font-size:24px;font-weight:800;letter-spacing:-.02em;color:var(--ink);margin-top:8px;font-variant-numeric:normal}
.appr-card .what{font-size:12.5px;color:var(--text-2);margin-top:2px}
.appr-card .cta{
  margin-top:12px;display:inline-flex;align-items:center;gap:6px;
  font-size:12.5px;font-weight:650;color:var(--brand);
}
.appr-card .cta svg{width:14px;height:14px;transition:transform .18s}
.appr-card:hover .cta svg{transform:translateX(2px)}
.appr-empty{
  border:1px dashed var(--border);border-radius:var(--r-lg);padding:16px;
  font-size:12.5px;color:var(--text-3);background:#FBFBFC;display:flex;align-items:center;gap:9px;
}
.appr-empty svg{width:16px;height:16px;color:var(--green-dot)}

.contact-mini{padding:14px 16px 16px;display:flex;gap:11px;align-items:center}
.contact-mini b{display:block;font-size:13px;font-weight:650;color:var(--ink)}
.contact-mini span{font-size:11.5px;color:var(--text-3)}
.contact-mini .cbtns{margin-left:auto;display:flex;gap:6px}
.cbtn{
  width:30px;height:30px;border-radius:9px;border:1px solid var(--border);background:#fff;
  display:grid;place-items:center;color:var(--brand);transition:all .15s;
}
.cbtn:hover{background:var(--brand-50);border-color:var(--brand-100);transform:translateY(-1px)}
.cbtn svg{width:14px;height:14px}
.cbtn.wide{width:auto;padding:0 12px;height:32px;display:inline-flex;gap:6px;font-size:12px;font-weight:600;white-space:nowrap;flex-shrink:0}

/* ============ Case view ============ */
.back{
  display:inline-flex;align-items:center;gap:7px;
  font-size:13px;font-weight:600;color:var(--text-2);
  padding:6px 10px;margin:-6px 0 14px -10px;border-radius:9px;
  transition:all .15s;
}
.back:hover{color:var(--ink);background:#EDEFF2}
.back svg{width:15px;height:15px;transition:transform .18s}
.back:hover svg{transform:translateX(-2px)}

.case-head{margin-bottom:18px}
.case-meta-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.case-id{
  font-family:var(--font-display);font-size:12.5px;font-weight:700;letter-spacing:.02em;
  color:var(--text-3);background:#EEF0F4;padding:3px 9px;border-radius:7px;
}
.case-head h1{
  font-family:var(--font-display);font-size:24px;font-weight:750;letter-spacing:-.022em;color:var(--ink);
  margin-top:10px;line-height:1.2;
}
.case-sub{margin-top:6px;font-size:13px;color:var(--text-2);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.case-sub svg{width:14px;height:14px;color:var(--text-3)}
.case-sub .sep{color:#CBD1DA}

/* stepper */
.stepper{
  display:flex;align-items:flex-start;
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:16px 18px 14px;margin-bottom:16px;box-shadow:var(--shadow-sm);
  overflow-x:auto;
}
.step{flex:1;min-width:86px;position:relative;text-align:center}
.step::before{
  content:"";position:absolute;top:11px;left:calc(-50% + 14px);right:calc(50% + 14px);
  height:2px;background:var(--border);border-radius:2px;
}
.step:first-child::before{display:none}
.step.done::before{background:var(--green-dot)}
.step.cur::before{background:linear-gradient(90deg,var(--green-dot),var(--amber-dot))}
.step .ic{
  width:22px;height:22px;border-radius:50%;margin:0 auto;
  display:grid;place-items:center;position:relative;z-index:1;
  background:#EDF0F4;color:var(--text-3);
  border:2px solid #EDF0F4;
  transition:all .3s ease;
}
.step .ic svg{width:11px;height:11px}
.step.done .ic{background:var(--green-dot);border-color:var(--green-dot);color:#fff}
.step.cur .ic{
  background:#fff;border-color:var(--amber-dot);color:var(--amber-dot);
  box-shadow:0 0 0 4px rgba(239,160,11,.14);
}
.step.cur.approved-cur .ic{border-color:var(--brand);color:var(--brand);box-shadow:0 0 0 4px rgba(14,74,140,.12)}
.step b{display:block;font-size:11px;font-weight:650;color:var(--ink);margin-top:7px;letter-spacing:.005em}
.step span{display:block;font-size:10px;color:var(--text-3);margin-top:1px}
.step.todo b{color:var(--text-3);font-weight:550}
.step>i{
  width:22px;height:22px;margin:0 auto;display:grid;place-items:center;
  border-radius:50%;background:#EDF0F4;color:var(--text-3);
  font-size:10px;font-style:normal;font-weight:750;position:relative;z-index:1;
}
.step.done>i{background:var(--green-dot);color:#fff}
.step>span>small{display:block;margin-top:2px;font-size:9.5px;line-height:1.35;color:var(--text-3)}

.case-grid{display:grid;grid-template-columns:minmax(0,1fr) 324px;gap:16px;align-items:start}
@media (max-width:1180px){.case-grid{grid-template-columns:minmax(0,1fr)}}

/* thread */
.thread{display:flex;flex-direction:column;gap:12px}
.ev{display:flex;gap:12px}
.ev .avatar{width:32px;height:32px;font-size:11.5px;margin-top:2px}
.ev-body{flex:1;min-width:0}
.ev-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
/* A name is typed by whoever reports, on the poster by anybody at all. One of
   50 letters with no space kept its width as an item of this row and pushed
   the case page 158px sideways on a phone (W-02): it may be narrower than
   itself, and then it breaks. */
.ev-head b{font-size:13px;font-weight:650;color:var(--ink);min-width:0;overflow-wrap:anywhere}
.ev-head .role{font-size:11px;color:var(--text-3);font-weight:500;min-width:0;overflow-wrap:anywhere}
.ev-head time{font-size:11px;color:var(--text-3);margin-left:auto;white-space:nowrap}
.bubble{
  margin-top:6px;background:var(--card);border:1px solid var(--border);
  border-radius:4px 14px 14px 14px;padding:11px 14px;
  font-size:13.5px;color:var(--text);box-shadow:var(--shadow-sm);
  line-height:1.55;
}
.ev.me .bubble{background:var(--brand-50);border-color:var(--brand-100);border-radius:14px 4px 14px 14px}
.photos{display:flex;gap:8px;margin-top:8px}
.photo{
  width:104px;height:74px;border-radius:10px;border:1px solid var(--border);
  background:
    radial-gradient(140% 90% at 20% 10%, #C7D5E4 0%, transparent 55%),
    radial-gradient(120% 100% at 85% 90%, #97A9BC 0%, transparent 50%),
    linear-gradient(160deg,#B4C2D2,#7F92A6);
  position:relative;overflow:hidden;cursor:pointer;
  transition:transform .16s,box-shadow .16s;
}
.photo:hover{transform:translateY(-2px) scale(1.02);box-shadow:var(--shadow-md)}
.photo svg{position:absolute;right:7px;bottom:6px;width:14px;height:14px;color:rgba(255,255,255,.85)}
.photo span{
  position:absolute;left:7px;bottom:5px;font-size:9px;font-weight:600;color:rgba(255,255,255,.9);
  letter-spacing:.02em;text-shadow:0 1px 2px rgba(0,0,0,.3);
}
.sysline{
  display:flex;align-items:center;gap:10px;padding:2px 0 2px 44px;
  font-size:12.5px;color:var(--text-2);
}
.sysline .sic{
  width:22px;height:22px;border-radius:8px;background:#EDF0F4;color:var(--text-2);
  display:grid;place-items:center;flex-shrink:0;margin-left:-32px;
}
.sysline .sic svg{width:12px;height:12px}
.sysline b{font-weight:650;color:var(--ink)}
.sysline time{margin-left:auto;font-size:11px;color:var(--text-3);white-space:nowrap}
.sysline.good .sic{background:var(--green-bg);color:var(--green)}
/* What is invoiced on a case, one line an invoice, above the line that
   offers the next draft (I-05). Filled after the page is drawn, and hidden
   until then so the thread keeps no gap for it. Each line ends in its way to
   the invoice, where the draft button stands on the line below. */
.billed{display:flex;flex-direction:column;gap:8px}
.billed[hidden]{display:none}
.billed .sysline .btn{margin-left:auto;flex-shrink:0;text-decoration:none}

/* offer card */
.offer{
  border:1px solid var(--brand-100);
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,#FFFFFF, #F7FAFE);
  box-shadow:var(--shadow-md);
  overflow:hidden;
  margin-left:44px;
  position:relative;
}
.offer::before{
  content:"";position:absolute;top:0;left:0;right:0;height:3px;
  background:linear-gradient(90deg,var(--brand),#3D6FB0);
}
.offer.approved::before{background:linear-gradient(90deg,#1FA35C,#15803D)}
.offer-h{display:flex;align-items:center;gap:10px;padding:15px 18px 0;flex-wrap:wrap}
.offer-h .oic{
  width:34px;height:34px;border-radius:10px;background:var(--brand-50);color:var(--brand);
  display:grid;place-items:center;flex-shrink:0;
}
.offer-h .oic svg{width:17px;height:17px}
.offer-h b{font-family:var(--font-display);font-size:15px;font-weight:700;letter-spacing:-.01em;color:var(--ink);display:block}
.offer-h .v{font-size:11.5px;color:var(--text-3)}
.offer-h .chip{margin-left:auto}
.rev-note{
  margin:12px 18px 0;padding:9px 12px;border-radius:10px;
  background:var(--brand-50);border:1px solid var(--brand-100);
  font-size:12.5px;color:var(--brand-700);display:flex;gap:8px;align-items:flex-start;
}
.rev-note svg{width:14px;height:14px;flex-shrink:0;margin-top:2px}
/* The note and each line of a quote are items of a flex row, and an item is
   never narrower than its longest word unless it is told it may be (the rule
   on <body>, F-009): a pasted address in either ran on under the card's edge
   and was cut there. It may, so it wraps. */
.rev-note > span{min-width:0}
.olines{padding:14px 18px 0}
.oline{
  display:flex;justify-content:space-between;gap:14px;
  padding:8.5px 0;border-bottom:1px dashed var(--border);
  font-size:13px;
}
.oline .d{color:var(--text-2);min-width:0}
.oline .p{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.oline.total{border-bottom:none;padding-top:12px}
.oline.total .d{font-weight:700;color:var(--ink);font-size:13.5px}
/* Proportional figures on the total: the display face draws a tabular full
   stop and comma a whole figure wide, so it read "4 . 200 , 50 kr ." */
.oline.total .p{font-family:var(--font-display);font-weight:800;font-size:19px;letter-spacing:-.02em;font-variant-numeric:normal}
.oline.total .p small{font-size:11px;color:var(--text-3);font-weight:500;letter-spacing:0}
.othreshold{
  margin:10px 18px 0;display:flex;align-items:center;gap:8px;
  font-size:12px;color:var(--amber);font-weight:600;
  background:var(--amber-bg);border:1px solid var(--amber-br);
  padding:8px 12px;border-radius:10px;
}
.othreshold svg{width:14px;height:14px;flex-shrink:0}
.ometa{display:flex;gap:16px;padding:10px 18px 0;font-size:11.5px;color:var(--text-3);flex-wrap:wrap}
.ometa b{color:var(--text-2);font-weight:600}
.ometa svg{width:13px;height:13px;vertical-align:-2px;margin-right:3px;flex-shrink:0}
/* The buttons under it bring the card's bottom padding. A card with none, a
   decided quote or a reader's view, ended on this line with its text on the
   edge (test round F-096). */
.ometa:last-child{padding-bottom:16px}
.oact{display:flex;gap:9px;padding:15px 18px 17px;flex-wrap:wrap;align-items:center}
.oact .right{margin-left:auto;font-size:11.5px;color:var(--text-3);display:flex;align-items:center;gap:6px}
.oact .right svg{width:13px;height:13px}
/* The supplier's answer panel puts its buttons inside a padded body, where
   .oact's own padding stood them 18px in from the text and 50px under it
   (V-39). There the row has none, and a gap only to what stands above it. */
.oact.bid-act{padding:0}
.oact.bid-act:not(:first-child){margin-top:12px}

.approved-note{
  margin:14px 18px 0;padding:12px 14px;border-radius:12px;
  background:var(--green-bg);border:1px solid var(--green-br);
  display:flex;gap:10px;align-items:center;
  animation:cardIn .45s cubic-bezier(.22,.9,.3,1) both;
}
.approved-note .ok{
  width:26px;height:26px;border-radius:50%;background:var(--green-dot);color:#fff;
  display:grid;place-items:center;flex-shrink:0;
}
.approved-note .ok svg{width:13px;height:13px}
.approved-note b{font-size:13px;color:var(--green);display:block}
.approved-note span{font-size:12px;color:#3D7A57}

.revision-box{margin:12px 18px 0;animation:cardIn .3s ease both}
.revision-box textarea{
  width:100%;min-height:74px;resize:vertical;
  border:1px solid var(--border);border-radius:11px;padding:10px 13px;
  font-size:13px;background:#fff;outline:none;
  transition:border-color .15s,box-shadow .15s;
}
.revision-box textarea:focus{border-color:#B9CDE6;box-shadow:0 0 0 3px rgba(14,74,140,.08)}
.revision-box .rb-act{display:flex;gap:8px;margin-top:9px}

/* composer */
.composer{
  margin-top:4px;margin-left:44px;
  display:flex;gap:9px;align-items:center;
  background:var(--card);border:1px solid var(--border);border-radius:13px;
  padding:7px 8px 7px 14px;box-shadow:var(--shadow-sm);
  transition:border-color .15s,box-shadow .15s;
}
.composer:focus-within{border-color:#B9CDE6;box-shadow:0 0 0 3px rgba(14,74,140,.08)}
.composer input{flex:1;border:none;outline:none;background:none;font-size:13.5px}
.composer input::placeholder{color:var(--text-3)}
/* The desk's reply box: several lines, as tall as its text (standalone.js
   fitComposer) up to nine or so, with the clip and the send button staying on
   the last line. */
.composer textarea{flex:1;min-width:0;border:none;outline:none;background:none;resize:none;font:inherit;font-size:13.5px;line-height:1.45;color:var(--text);padding:6px 0;max-height:190px;overflow-y:auto}
.composer textarea::placeholder{color:var(--text-3)}
.composer:has(textarea){align-items:flex-end}
.composer .attach{color:var(--text-3);width:32px;height:32px;border-radius:9px;display:grid;place-items:center;transition:all .15s}
.composer .attach:hover{background:#F1F2F5;color:var(--text)}
.composer .send{
  width:34px;height:34px;border-radius:10px;background:var(--brand);color:#fff;
  display:grid;place-items:center;transition:all .15s;
  box-shadow:0 2px 6px -2px rgba(10,52,98,.5);
}
.composer .send:hover{background:var(--brand-600);transform:translateY(-1px)}
.composer .send svg{width:15px;height:15px}

/* rail cards (case) */
.rc{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-sm)}
.rc-h{padding:13px 16px 0;font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
.rc-b{padding:11px 16px 14px}
.kv{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:6.5px 0;font-size:12.5px}
.kv + .kv{border-top:1px solid var(--border-2)}
.kv .k{color:var(--text-3)}
.kv .v{font-weight:600;color:var(--ink);text-align:right;min-width:0}
.kv .v.link{color:var(--brand);cursor:pointer}
.kv .v.link:hover{text-decoration:underline}
/* A file as a value: the invoice under "Slutpris" (S55-005). It was the 30px
   icon button with the file's name written in it, so a name with nowhere to
   break ran out of the card and the page, 481px wide on a 390px phone. It is
   the link it reads as, and the name wraps anywhere inside the value, as the
   files card above wraps the same name. */
.kv .v .kv-file{padding:0;border:0;background:none;font:inherit;color:var(--link);text-align:right;overflow-wrap:anywhere;cursor:pointer}
.kv .v .kv-file:hover{text-decoration:underline}
/* An invoice number in a label is the way to that invoice (I-03). */
.kv .k a{color:var(--brand);text-decoration:none}
.kv .k a:hover{text-decoration:underline}
/* On a draft's account the amount stays on one line and the label beside it
   takes the wrap (the repair round, 6 October 2026): at 390 px, with six
   invoice numbers in the label, the amount broke in two, "6.000" over "kr.".
   Not to shrink either: an amount that may not wrap and may shrink runs out
   of the panel instead. */
.inv-account .kv .v{white-space:nowrap;flex-shrink:0}
/* ⚠️ A REQUEST FOR EXTRA WORK CUT ITS OWN ANSWER ON A PHONE (C-05). The
   amount and the chip shared the value, and the value shrinks to make room
   for the reason: at 390px it was 192px wide, "Godkendt af Test Kæde
   Godkender" is 233, and a chip never paints outside what holds it, so it
   ended at "Godk". Here the three are the row's own children. They stand on
   one line where the row holds them, with the reason no narrower than two
   fifths of it. Where it does not, the reason and the amount keep the first
   line and the chip goes under the amount with the whole width to itself;
   a chip longer than that takes two lines (chip wraps). The amount keeps the
   12px to the reason and the 4px to the chip it had as one value. */
.kv.extra{flex-wrap:wrap;justify-content:flex-end;gap:4px}
.kv.extra .k{flex:1 1 0;min-width:40%}
.kv.extra .v{flex:none;margin-left:8px;white-space:nowrap}

.agent-card{display:flex;gap:11px;align-items:center}
.agent-card .avatar{width:40px;height:40px;font-size:13px}
.agent-card b{display:block;font-size:13.5px;font-weight:650;color:var(--ink)}
.agent-card .r1{font-size:11.5px;color:var(--text-2)}
.agent-card .r2{font-size:10.5px;color:var(--text-3);margin-top:1px}
.agent-actions{display:flex;gap:7px;margin-top:11px}
.agent-actions .cbtn{flex:1;height:32px;display:flex;gap:6px;align-items:center;justify-content:center;font-size:11.5px;font-weight:600;color:var(--brand)}

.hist{position:relative;padding-left:16px}
.hist::before{content:"";position:absolute;left:4px;top:8px;bottom:8px;width:2px;background:var(--border-2);border-radius:2px}
.hi{position:relative;padding:6px 0 6px 6px}
.hi::before{
  content:"";position:absolute;left:-16px;top:12px;width:10px;height:10px;border-radius:50%;
  background:#fff;border:2.5px solid #C4CBD6;
}
.hi.cur::before{border-color:var(--amber-dot)}
.hi.ok::before{border-color:var(--green-dot);background:var(--green-dot)}
.hi b{font-size:12.5px;font-weight:650;color:var(--ink);display:flex;justify-content:space-between;gap:8px}
.hi b .pr{font-variant-numeric:tabular-nums}
.hi span{font-size:11px;color:var(--text-3);display:block;margin-top:1px}
.hi .st-note{font-size:11px;font-weight:600;margin-top:2px}
.hi .st-note.amber{color:var(--amber)}
.hi .st-note.green{color:var(--green)}
.hi .st-note.gray{color:var(--text-3)}

.doc{display:flex;align-items:center;gap:10px;padding:7px 0;font-size:12.5px}
.doc + .doc{border-top:1px solid var(--border-2)}
.doc .dic{
  width:30px;height:30px;border-radius:9px;background:#F2F3F6;color:var(--text-2);
  display:grid;place-items:center;flex-shrink:0;
}
.doc .dic svg{width:14px;height:14px}
.doc .dic.pdf{background:var(--red-bg);color:var(--red)}
.doc .dic.img{background:var(--brand-50);color:var(--brand)}
.doc b{font-weight:600;color:var(--ink);display:block;line-height:1.3}
.doc span{font-size:10.5px;color:var(--text-3)}
.doc .sz{margin-left:auto;font-size:10.5px;color:var(--text-3);white-space:nowrap}
/* ⚠️ THE NAME IS THE PART OF THE ROW THAT GIVES WAY (the rest of F-009).
   A file is called what the phone or the bookkeeping system called it:
   "Faktura_2026_10_04_Leverandor_Nord_butik_aflobsrens_final.pdf.png" has no
   place to break, and a linked case brings its whole title. The row is a flex
   row and its text span kept min-width:auto, so it refused to be narrower than
   that one word and the case page grew to 1.480 px behind a 324 px rail, on
   every console. The text span (the one with no class) may shrink to nothing
   and wraps inside what is left; the icon, the size, the buttons and a chip
   keep their own width, so the squeeze never lands on them instead. */
.doc>*{flex-shrink:0}
.doc>span:not([class]){flex-shrink:1;min-width:0}

/* ============ Tables / list pages ============ */
/* Svartider on Settings (WP33): four urgencies against two or three columns,
   narrow enough to scroll sideways on a phone rather than wrap. */
.sla-grid{width:100%;border-collapse:collapse;font-size:12.5px}
.sla-grid th{text-align:left;padding:6px 8px;border-bottom:1px solid var(--border);color:var(--text-3);font-weight:600;white-space:nowrap}
.sla-grid td{padding:6px 8px;border-bottom:1px solid var(--border-2);vertical-align:middle}
/* ⚠️ THE ONE WITH THE FIELDS IN IT DOES NOT FIT A PHONE, AND SCROLLING IT CUT
   "UDFØRT INDEN FOR" AT THE CARD'S EDGE (X-07, X-15). Three columns of
   fields are 613px (650 with a phone's taller fields), in a card of 324, so
   the done-by time was cut in two and "Tælles" out of sight, on head
   office's Settings and on the plain customer's.
   Where the card is narrower than the table, an urgency is a block of its
   own: its name, then each field on a line with its heading in front
   (data-k), every one within reach of a thumb. Up to 700px, and again from
   921, where the menu is back beside the page, to 960: at 680 and at 945 the
   card is 613px again. The tables that are only read wrap their words and
   fit as they are. */
@media (max-width:700px),(min-width:921px) and (max-width:960px){
  .sla-form,.sla-form tbody,.sla-form tr,.sla-form td{display:block}
  .sla-form thead{display:none}
  .sla-form tr{padding:8px 0}
  .sla-form tr + tr{border-top:1px solid var(--border-2)}
  .sla-form td{padding:3px 0;border-bottom:0}
  .sla-form td[data-k]{display:flex;align-items:center;justify-content:space-between;gap:12px}
  .sla-form td[data-k]::before{content:attr(data-k);font-size:12px;font-weight:600;color:var(--text-3)}
}
.tbl{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.tbl-toolbar{display:flex;align-items:center;gap:8px;padding:14px 18px 10px;flex-wrap:wrap}
.tbl-toolbar .grow{flex:1}
/* The desk's inbox has thirteen views and an order to choose: the views wrap
   inside what the order leaves them, so the two share a row on a desk, and on
   a phone the order drops under them. */
.tbl.inbox .tbl-toolbar .pills{flex:1 1 420px}
/* A row is 46px high with no padding of its own, and the desk's title cell
   holds the title, its line and both service targets: always taller than
   that, so the block touched the border above it and the next row's title
   (W-25). As a table only; the cards under 1180px bring their own padding. */
.tbl.inbox .trow{padding-top:10px;padding-bottom:10px}
/* The same for "Afregning" (S55-014): where "Placeret på" holds its invoice
   numbers over "Placér" and "Tilbagefør", and "Fra" its payer over a long
   reference, the cell is taller than the row and its first line touched the
   border above it. As a table only; under 641px it is a card. */
@media (min-width:641px){.tbl[data-settle] .trow{padding-top:8px;padding-bottom:8px}}
.t-search{
  display:flex;align-items:center;gap:8px;height:34px;padding:0 12px;width:250px;
  background:#FAFAFB;border:1px solid var(--border);border-radius:10px;color:var(--text-3);
  transition:border-color .15s,box-shadow .15s;
}
.t-search:focus-within{border-color:#B9CDE6;box-shadow:0 0 0 3px rgba(14,74,140,.08);background:#fff}
.t-search input{border:none;outline:none;background:none;flex:1;font-size:13px;color:var(--text)}
.t-search svg{width:14px;height:14px}
.trow{
  display:grid;align-items:center;gap:12px;
  padding:0 18px;min-height:46px;width:100%;text-align:left;
  font-size:13px;transition:background .13s;
}
/* A grid item defaults to min-width:auto, which means it refuses to shrink
   below its content — so a nowrap chip in a fixed column overflows the column
   instead of the column containing it. This is the half of that fix that
   belongs to the row rather than to the chip. */
.trow > *, .trow-h > *{min-width:0}
.trow + .trow, .trow-h + .trow{border-top:1px solid var(--border-2)}
button.trow:hover{background:#F8F9FB;cursor:pointer}
.trow-h{
  display:grid;align-items:center;gap:12px;padding:10px 18px;
  font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-3);
  background:#FAFAFB;border-top:1px solid var(--border-2);
  /* ⚠️ A COLUMN HEADING IS NEVER BROKEN INSIDE A WORD (W-01). The rule on
     <body> is for what people type; a heading is our own word, and when its
     column is a few pixels short the rule cut it in two: "SELVBETJENIN" over
     "G" on a desk, one letter per line where a column had collapsed. It may
     reach into the gap beside it, as it always did. A column too narrow for
     its heading is a layout to fix (cards or a floor, below), not a word to
     break. */
  overflow-wrap:normal;
}
.g-sager{grid-template-columns:86px 1.5fr 1fr 110px 130px 90px 110px}
.g-fakt{grid-template-columns:96px 1fr 1.1fr 110px 110px 110px}
.g-brugere{grid-template-columns:2fr 1.4fr 1.2fr 1fr 90px}
.g-afd{grid-template-columns:1.6fr 100px 130px 1fr 1fr 40px}
.trow .tid{font-family:var(--font-display);font-size:12px;font-weight:700;color:var(--text-3)}
/* A title is typed by a person, and a pasted address has nowhere to break:
   one such title made the store's list 2300px wide. */
.trow .tt b{display:block;font-size:13px;font-weight:650;color:var(--ink);line-height:1.3;overflow-wrap:anywhere}
.trow .tt span{font-size:11.5px;color:var(--text-3)}
.trow .mut{color:var(--text-2);font-size:12.5px}
.trow .mut2{color:var(--text-3);font-size:12px}
.trow .amt{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;text-align:right}
.trow .aend{display:flex;justify-content:flex-end}
.trow .who{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-2)}
.trow .who .avatar{width:24px;height:24px;font-size:9px}
.trow .arr{color:var(--text-3);display:grid;place-items:center}
.trow .arr svg{width:14px;height:14px}
.empty{
  padding:36px 20px;text-align:center;color:var(--text-3);font-size:13px;
}
.rolechip{
  display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:7px;
  font-size:11px;font-weight:650;background:#F2F3F6;color:var(--text-2);border:1px solid var(--border);
}
.rolechip.admin{background:var(--brand-50);color:var(--brand);border-color:var(--brand-100)}
.rolechip.mod{background:#F3EEFB;color:#6D3FB8;border-color:#E4D7F6}
.rolechip.afd{background:var(--green-bg);color:var(--green);border-color:var(--green-br)}

/* ============ Insights bars ============ */
.bars{padding:8px 18px 16px}
.bar-row{display:grid;grid-template-columns:150px 1fr 84px;gap:12px;align-items:center;padding:6px 0;font-size:12.5px}
/* A label wraps; it is never cut with three dots (X-09). "Phone via the
   service desk" needs 159px of the column's 150, and nobody can hover over a
   cut label on a phone to read the rest. */
.bar-row .bl{color:var(--text-2);line-height:1.3;overflow-wrap:anywhere}
.bar-row .bv{font-weight:650;color:var(--ink);text-align:right;font-variant-numeric:tabular-nums}
.bar-track{height:9px;border-radius:6px;background:#EFF1F4;overflow:hidden}
/* display:block, or the whole chart is empty grey tracks. .bar-fill is a span
   and its parent is not a flex container, so it stays inline and an inline box
   ignores width and height — it renders at its content width, which is zero,
   because a bar has no text in it. The prototype had the same line and the same
   silent nothing; it only shows up once the numbers behind the bars are real. */
.bar-fill{display:block;height:100%;border-radius:6px;background:linear-gradient(90deg,#2E6FB2,var(--brand));transition:width .6s cubic-bezier(.22,.9,.3,1)}
.bar-fill.green{background:linear-gradient(90deg,#35B571,#1F8B4E)}
.bar-fill.amber{background:linear-gradient(90deg,#F3B13C,#DB8E08)}
.split2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:1180px){.split2{grid-template-columns:minmax(0,1fr)}}

/* ============ Settings ============ */
.set-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
/* minmax(0,1fr), not 1fr: a 1fr track never shrinks below its widest card's
   min-content, so one wide row in one card pushed every settings card to
   476px and the whole page scrolled sideways on a 375px phone (walk, 28 Sep). */
@media (max-width:1180px){.set-grid{grid-template-columns:minmax(0,1fr)}}
/* ⚠️ ONE COLUMN UP TO 1340px WHERE THE RESPONSE TIMES ARE (head office and the
   plain customer). Their table of two figures, two units and a clock for each
   urgency is 651px at its narrowest for somebody who may change it, and a 1fr
   column cannot be narrower than what is in it: with the 366px the other
   column needs, the two fit from 1325px. Under that the page went sideways,
   118px at 1181 and 19px at 1280, the width of a common laptop. The desk's and
   the supplier's Settings have no such table and keep their two columns. */
@media (max-width:1340px){.set-grid:has(#svartider){grid-template-columns:minmax(0,1fr)}}
.set-b{padding:6px 18px 16px}
/* ⚠️ A CONTROL WIDER THAN A SWITCH LEFT THE SENTENCE A COLUMN BESIDE IT
   (X-08): on a phone 117px for "Kræv to-faktor", twelve lines of it, and
   98px for how long closed cases stay; and 133px for that one on a desk,
   where Settings is two cards wide. A sentence keeps 200px: a control that
   does not fit beside that goes under it, and the sentence has the card. A
   switch, a radio or one button still fits and stays where it was. */
.set-row{display:flex;flex-wrap:wrap;align-items:center;gap:14px;padding:12px 0}
.set-row + .set-row{border-top:1px solid var(--border-2)}
.set-row .si{flex:1 1 200px}
.set-row .si b{display:block;font-size:13px;font-weight:650;color:var(--ink)}
.set-row .si span{font-size:12px;color:var(--text-3);line-height:1.45;display:block;margin-top:1px}
.f-input{
  height:36px;padding:0 12px;border:1px solid var(--border);border-radius:10px;
  background:#fff;outline:none;font-size:13.5px;
  transition:border-color .15s,box-shadow .15s;
}
.f-input:focus{border-color:#B9CDE6;box-shadow:0 0 0 3px rgba(14,74,140,.08)}
.f-input.amt{width:130px;text-align:right;font-weight:650;font-variant-numeric:tabular-nums}
select.f-input{width:100%;appearance:auto;cursor:pointer}
textarea.f-input{height:auto;min-height:84px;padding:10px 12px;resize:vertical;width:100%}
/* A file field (V-35, FogiDeskChrome.filePicker). The browser's own control is
   in the page and takes the keyboard, but it says "Choose Files · No file
   chosen" in the browser's language, so it is not drawn: its label is, as one
   of our buttons, with what was chosen beside it. */
.filepick{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px}
.filepick input[type="file"]{position:absolute;left:0;top:0;width:1px;height:1px;opacity:0;overflow:hidden}
.filepick input[type="file"]:focus-visible + label{outline:2px solid rgba(14,74,140,.45);outline-offset:2px}
.filepick label{cursor:pointer}
.filepick-names{flex:1 1 140px;min-width:0;font-size:12.5px;color:var(--text-2);overflow-wrap:anywhere}
.filepick-names:empty{display:none}
.filepick + .hint{margin-top:6px}
@media (pointer: coarse), (max-width: 640px){
  .filepick label{min-height:44px}
}
.f-label{display:block;font-size:12px;font-weight:650;color:var(--text-2);margin:0 0 5px}
/* ⚠️ AN SVG WITH NO SIZE IS 300x150, NOT "AS BIG AS THE TEXT".
   Every icon in this product is a bare <svg viewBox="0 0 24 24"> with no width
   or height attribute, sized by whatever rule the container carries — .btn svg,
   .nav-item svg, and thirty more. A label had no such rule, so the camera on
   "Add a photo" in the employee report form rendered at the CSS default size
   for a replaced element with no intrinsic dimensions: three hundred pixels
   wide, filling the form. Nothing was wrong with the icon or the markup; the
   rule simply did not exist for this container. */
.f-label svg{width:14px;height:14px;vertical-align:-2px;margin-right:2px;flex-shrink:0}
/* A summary dressed as a field label keeps its arrow (F-053). display:block
   above takes the disclosure marker away, so "Telefon, kontakt, åbningstider
   og adgang" in the location form read as a caption with nothing under it,
   and the hours and the way in, which a craftsman needs, sat unseen inside. */
summary.f-label{display:list-item;cursor:pointer}
.f-group{margin-bottom:13px}
/* The helper line under a field, in a card or in a dialog. There was no base
   rule (only .panel-h .hint and the printed sheet's), so everywhere else a
   hint read as body copy: larger and darker than the thing it explains. */
.hint{font-size:12.5px;line-height:1.45;color:var(--text-3)}
.tgl{
  width:40px;height:24px;border-radius:999px;background:#DFE3E9;position:relative;flex-shrink:0;
  transition:background .18s;border:none;cursor:pointer;
}
.tgl::after{
  content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(15,21,34,.25);
  transition:transform .18s cubic-bezier(.34,1.3,.5,1);
}
.tgl.on{background:var(--green-dot)}
.tgl.on::after{transform:translateX(16px)}
.radio-row{display:flex;gap:8px;flex-wrap:wrap}
.radio-pill{
  border:1px solid var(--border);border-radius:11px;padding:10px 13px;background:#fff;
  text-align:left;flex:1;min-width:180px;transition:all .15s;cursor:pointer;
}
.radio-pill:hover{border-color:#CBD3DE}
.radio-pill.on{border-color:var(--brand);background:var(--brand-50);box-shadow:0 0 0 1px var(--brand)}
.radio-pill b{display:block;font-size:13px;font-weight:650;color:var(--ink)}
.radio-pill span{font-size:11.5px;color:var(--text-2);display:block;margin-top:2px;line-height:1.4}

/* ============ Command palette (from v3, v1-skinned) ============ */
.ov-cmd{
  position:fixed;inset:0;z-index:300;
  background:rgba(20,26,38,.3);
  backdrop-filter:blur(5px);
  -webkit-backdrop-filter:blur(5px);
  display:grid;place-items:start center;padding-top:13vh;
  animation:fadeIn .14s ease both;
}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.cmd{
  width:min(600px,92vw);
  background:rgba(255,255,255,.94);
  backdrop-filter:blur(24px) saturate(1.7);
  -webkit-backdrop-filter:blur(24px) saturate(1.7);
  border-radius:16px;
  box-shadow:var(--shadow-lg);
  border:1px solid rgba(15,21,34,.06);
  overflow:hidden;
  animation:cmdPop .2s cubic-bezier(.34,1.3,.5,1) both;
}
@keyframes cmdPop{from{opacity:0;transform:scale(.97) translateY(-7px)}to{opacity:1;transform:none}}
.cmd-in{display:flex;align-items:center;gap:11px;padding:15px 17px;border-bottom:1px solid var(--border-2)}
.cmd-in svg{width:17px;height:17px;color:var(--text-3);flex-shrink:0}
.cmd-in input{flex:1;background:none;border:none;outline:none;font-size:15.5px;color:var(--ink)}
.cmd-in input::placeholder{color:var(--text-3)}
.cmd-list{max-height:350px;overflow-y:auto;padding:7px}
.cgroup{font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:9px 11px 4px}
.citem{
  width:100%;display:flex;align-items:center;gap:11px;
  padding:8px 11px;border-radius:10px;text-align:left;
  font-size:13.5px;transition:background .1s;
}
.citem .ci{
  width:28px;height:28px;border-radius:8px;display:grid;place-items:center;flex-shrink:0;
  background:#F2F3F6;border:1px solid var(--border);color:var(--text-2);
}
.citem .ci svg{width:13.5px;height:13.5px}
.citem .ci.g{background:var(--green-bg);color:var(--green);border-color:var(--green-br)}
.citem .ci.a{background:var(--amber-bg);color:var(--amber);border-color:var(--amber-br)}
.citem .ci.r{background:var(--red-bg);color:var(--red);border-color:var(--red-br)}
.citem .ci.b{background:var(--brand-50);color:var(--brand);border-color:var(--brand-100)}
.citem b{font-weight:550;color:var(--ink)}
.citem .sub{font-size:11.5px;color:var(--text-3);margin-left:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.citem .k{margin-left:auto}
.citem.sel{background:var(--brand-50)}
.cmd-foot{
  display:flex;gap:15px;padding:10px 15px;border-top:1px solid var(--border-2);
  font-size:11px;color:var(--text-3);
}
.cmd-foot span{display:flex;align-items:center;gap:5px}
.cmd-empty{padding:28px;text-align:center;color:var(--text-3);font-size:13px}

/* ============ Modal ============ */
.m-ov{
  position:fixed;inset:0;z-index:280;
  background:rgba(20,26,38,.34);
  backdrop-filter:blur(4px);
  display:grid;place-items:center;padding:20px;
  animation:fadeIn .15s ease both;
}
.modal{
  width:min(560px,94vw);max-height:88vh;overflow-y:auto;
  background:var(--card);border-radius:18px;box-shadow:var(--shadow-lg);
  animation:cmdPop .22s cubic-bezier(.34,1.3,.5,1) both;
}
.m-h{display:flex;align-items:center;gap:10px;padding:18px 20px 0}
.m-h h3{font-family:var(--font-display);font-size:18px;font-weight:750;letter-spacing:-.02em;color:var(--ink);flex:1}
/* ⚠️ .m-x IS TWO THINGS: the round ✕ in the corner, and the hook openModal
   closes a dialog by. A dozen "Annullér" and "Luk" buttons carry it for the
   hook, and this box squeezed each of them into 32 pixels, so "Annullér" read
   "Annullé" behind the button beside it (test round F-095). The box is for the
   icon; a .btn that closes keeps the shape of a button. */
.m-x:not(.btn){
  width:32px;height:32px;border-radius:9px;display:grid;place-items:center;color:var(--text-3);
  transition:all .15s;
}
.m-x:not(.btn):hover{background:#F1F2F5;color:var(--ink)}
.m-x svg{width:16px;height:16px}
.m-b{padding:14px 20px 6px}
/* The buttons wrap onto a second line rather than run out of the dialog: a
   row that does not fit, flush right, spilled off the LEFT edge, where
   nothing scrolls to, and "Annullér" was cut in two at 390px (w12b P-03). */
.m-f{display:flex;flex-wrap:wrap;gap:9px;justify-content:flex-end;padding:12px 20px 18px}
/* A title wrapped in its own block (the bell, a new case) still pushes the
   close button to the right edge: flex:1 was on the h3 alone, so a wrapped
   title left the ✕ sitting beside it. */
.m-h>div:first-child{flex:1;min-width:0}
/* The search dialog (fogidesk-chrome.js openSearch): one full-width field and
   rows that look pressable. */
.srch-in{width:100%}
.srch-list{margin:10px -8px 8px}
.srch-g{font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-3);padding:10px 8px 4px}
.srch-row{display:block;width:100%;text-align:left;padding:8px;border-radius:10px;font-size:13.5px;line-height:1.4;color:var(--text);transition:background .12s}
.srch-row:hover,.srch-row:focus-visible{background:#F4F6F9}
html.dark .srch-row:hover,html.dark .srch-row:focus-visible{background:#1B212C}
.srch-row b{font-weight:650;color:var(--ink)}
.srch-t{display:block}
.srch-s{display:block;font-size:12px;color:var(--text-3)}
.srch-note{padding:8px;font-size:13px;color:var(--text-3)}
.f-2col{display:grid;grid-template-columns:1fr 1fr;gap:12px}

/* toast
   ⚠️ FROM EDGE TO EDGE, NOT FROM THE MIDDLE (W-03). The box started at
   left:50% and was pulled back by half of itself, so it could never be wider
   than half the screen: on a phone a toast was 195px and "Sendt tilbage ·
   leverandøren har fået at vide hvorfor" stood on four lines over the
   history. The box is the screen less a margin and centres what is in it; a
   toast is as wide as its sentence, up to what one line of reading holds. */
.toasts{position:fixed;bottom:24px;left:12px;right:12px;z-index:400;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{
  max-width:min(100%,680px);
  display:flex;align-items:center;gap:10px;
  background:var(--ink);color:#fff;
  padding:11px 18px 11px 14px;border-radius:13px;
  font-size:13px;font-weight:550;
  box-shadow:var(--shadow-lg);
  animation:toastIn .35s cubic-bezier(.22,.9,.3,1) both;
}
.toast.out{animation:toastOut .3s ease both}
.toast .tic{
  width:22px;height:22px;border-radius:50%;background:var(--green-dot);
  display:grid;place-items:center;flex-shrink:0;
}
.toast .tic.info{background:#3D6FB0}
.toast .tic svg{width:12px;height:12px}
/* A toast that has to be answered (X-13): it stays until it is, and it can be
   pressed. The box around the toasts lets every click through to the page
   under it, so this one takes its own back. Its sentence wraps over the
   buttons on a phone. */
.toast.ask{pointer-events:auto;flex-wrap:wrap;max-width:min(100%,780px);padding-right:12px;line-height:1.35}
.toast.ask .tx{flex:1 1 220px;min-width:0}
.toast.ask button{flex-shrink:0;border-radius:8px;padding:7px 12px;font-size:12.5px;font-weight:650;white-space:nowrap}
.toast.ask button:not(.quiet){background:#fff;color:var(--ink)}
.toast.ask button.quiet{opacity:.85;text-decoration:underline;text-underline-offset:2px}
@keyframes toastIn{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(10px) scale(.97)}}

/* proto pill */
.proto{
  position:fixed;right:18px;bottom:16px;z-index:150;
  font-size:10.5px;font-weight:650;letter-spacing:.04em;color:var(--text-3);
  background:rgba(255,255,255,.85);backdrop-filter:blur(8px);
  border:1px solid var(--border);border-radius:999px;padding:5px 11px;
}

/* check draw */
.checkdraw{stroke-dasharray:24;stroke-dashoffset:24;animation:draw .45s .1s ease forwards}
@keyframes draw{to{stroke-dashoffset:0}}

/* ============ Persona switcher (demo only) ============ */
.switcher{position:fixed;right:18px;bottom:52px;z-index:260;display:flex;justify-content:flex-end}
.sw-btn{
  display:flex;align-items:center;gap:8px;
  height:34px;padding:0 14px 0 9px;border-radius:999px;
  background:var(--ink);color:#fff;font-size:12px;font-weight:650;
  box-shadow:var(--shadow-lg);
  transition:transform .16s ease;
}
.switcher:hover .sw-btn{transform:translateY(-1px)}
.sw-btn .swd{width:19px;height:19px;border-radius:50%;background:linear-gradient(145deg,#3D6FB0,#0E4A8C);display:grid;place-items:center;font-size:8px;font-weight:800;flex-shrink:0}
.sw-menu{
  position:absolute;right:0;bottom:42px;width:262px;
  background:var(--card);border:1px solid var(--border);border-radius:16px;
  box-shadow:var(--shadow-lg);padding:8px;
  opacity:0;pointer-events:none;transform:translateY(8px) scale(.98);
  transition:opacity .16s ease,transform .18s cubic-bezier(.22,.9,.3,1);
}
/* invisible bridge across the gap to the button, so hover isn't lost mid-move.
   Inherits pointer-events:none while the menu is closed (click-through). */
.sw-menu::before{content:"";position:absolute;left:-8px;right:-8px;bottom:-16px;height:18px}
.switcher:hover .sw-menu,.switcher:focus-within .sw-menu{opacity:1;pointer-events:auto;transform:none}
.sw-t{display:block;font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-3);padding:6px 10px 5px}
.sw-menu a{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;text-decoration:none;color:var(--text);transition:background .13s}
.sw-menu a:hover{background:#F4F5F8}
.sw-menu a.on{background:var(--brand-50)}
.sw-menu a .swa{width:28px;height:28px;border-radius:9px;display:grid;place-items:center;color:#fff;font-size:10px;font-weight:750;flex-shrink:0}
.sw-menu a b{display:block;font-size:12.5px;font-weight:650;color:var(--ink);line-height:1.2}
.sw-menu a span{font-size:10.5px;color:var(--text-3)}

/* ============ Auth pages (login + QR) ============ */
.auth-wrap{
  /* The brandline sits UNDER the card in the flow now, not fixed over it: at
     375 wide the fixed one was drawn across the first category tile, and the
     card's 96vw plus this padding was 3px wider than the phone. */
  min-height:100vh;min-height:100dvh;display:grid;place-items:center;align-content:center;gap:18px;
  grid-template-columns:minmax(0,1fr);padding:30px 18px 24px;position:relative;
  background:
    radial-gradient(52% 44% at 10% 0%, rgba(14,74,140,.08), transparent 60%),
    radial-gradient(44% 40% at 100% 100%, rgba(34,165,94,.05), transparent 60%),
    var(--bg);
}
.auth-card{
  width:100%;max-width:432px;min-width:0;background:var(--card);
  border:1px solid var(--border);border-radius:22px;box-shadow:var(--shadow-lg);
  padding:32px 32px 26px;animation:cmdPop .3s cubic-bezier(.22,.9,.3,1) both;
}
.auth-card.wide{width:100%;max-width:600px;padding:28px 30px 24px}
@media (max-width:480px){.auth-wrap{padding:16px 12px 24px}}
.auth-logo{display:flex;align-items:center;gap:12px;margin-bottom:20px}
.auth-logo .logo-mark{width:44px;height:44px;border-radius:13px;font-size:17px}
.auth-h1{font-family:var(--font-display);font-size:21px;font-weight:750;letter-spacing:-.02em;color:var(--ink)}
.auth-sub{font-size:13px;color:var(--text-2);margin-top:4px;line-height:1.55}
.auth-sub svg{width:15px;height:15px;color:var(--text-3);flex-shrink:0;margin-top:2px}
.auth-field{margin-top:15px}
.auth-field label{display:block;font-size:12px;font-weight:650;color:var(--text-2);margin-bottom:6px}
.auth-field .f-input{width:100%;height:42px;border-radius:11px;font-size:14px}
.auth-btn{width:100%;height:42px;margin-top:14px;font-size:14px}
.auth-remember{display:flex;align-items:flex-start;gap:9px;margin-top:13px;font-size:13px;font-weight:600;color:var(--text-2);cursor:pointer}
.auth-remember input{width:17px;height:17px;margin:1px 0 0;flex-shrink:0;accent-color:var(--brand)}
.auth-remember small{display:block;font-size:11.5px;font-weight:500;color:var(--text-3);margin-top:2px;line-height:1.45}
.auth-alt{width:100%;margin-top:10px;text-align:center;font-size:12.5px;font-weight:600;color:var(--brand);padding:8px;border-radius:9px}
.auth-alt:hover{background:var(--brand-50)}
.auth-sent{margin-top:16px;background:var(--green-bg);border:1px solid var(--green-br);border-radius:14px;padding:15px;display:flex;gap:12px;align-items:flex-start;animation:cardIn .35s ease both}
.auth-sent .aic{width:34px;height:34px;border-radius:10px;background:var(--green-dot);color:#fff;display:grid;place-items:center;flex-shrink:0}
.auth-sent .aic svg{width:16px;height:16px}
.auth-sent b{font-size:13.5px;color:var(--green);display:block}
.auth-sent span{font-size:12px;color:#3D7A57;line-height:1.5;display:block;margin-top:2px}
.auth-note{margin-top:18px;padding-top:14px;border-top:1px solid var(--border-2);font-size:12px;color:var(--text-3);text-align:center;line-height:1.7}
.auth-note a{color:var(--link);font-weight:600;text-decoration:none;cursor:pointer}
.auth-note a:hover{text-decoration:underline}
.auth-brandline{position:static;text-align:center;font-size:11px;color:var(--text-3);font-weight:500;pointer-events:none}
.auth-brandline b{color:var(--text-2)}
.auth-brandline.brand-lockup{display:flex;align-items:center;justify-content:center;gap:9px;flex-wrap:wrap}
/* The lockup's display:flex outranks the hidden attribute, so a working poster
   that hid it (D8) still wore FogiDesk's mark under the store's own card. */
.auth-brandline[hidden]{display:none}
.auth-brandline.brand-lockup img{width:92px;height:auto;display:block}
.auth-brandline.brand-lockup .reverse{display:none}
html.dark .auth-brandline.brand-lockup .primary{display:none}
html.dark .auth-brandline.brand-lockup .reverse{display:block}
.fogidesk-logo{display:block;width:112px;height:auto;max-width:100%}
.fogidesk-symbol{display:block;width:30px;height:32px;object-fit:contain}
html.dark .fogidesk-logo.primary{display:none}
html:not(.dark) .fogidesk-logo.reverse{display:none}
.qr-public-terminal .switcher,.qr-public-terminal .proto{display:none!important}
.demo-strip{margin-top:20px;border-top:1px dashed var(--border);padding-top:15px}
.demo-strip .dt{font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3);margin-bottom:4px;text-align:center}
.demo-strip a{
  display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:11px;
  border:1px solid var(--border);margin-top:7px;text-decoration:none;color:var(--text);
  transition:all .15s;background:#FDFDFE;
}
.demo-strip a:hover{border-color:#C8D2DF;transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.demo-strip a .swa{width:30px;height:30px;border-radius:9px;color:#fff;display:grid;place-items:center;font-size:10.5px;font-weight:750;flex-shrink:0}
.demo-strip a b{display:block;font-size:12.5px;font-weight:650;color:var(--ink);line-height:1.25}
.demo-strip a span{font-size:11px;color:var(--text-3)}
.demo-strip a svg{margin-left:auto;width:14px;height:14px;color:var(--text-3);flex-shrink:0}

/* ============ Rapportér-flow (employee + QR) ============ */
.cat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;padding:4px 0 2px}
@media (max-width:760px){.cat-grid{grid-template-columns:repeat(2,1fr)}}
.cat-tile{
  border:1px solid var(--border);border-radius:14px;background:#FDFDFE;
  padding:15px 10px 12px;text-align:center;cursor:pointer;
  transition:all .16s ease;display:flex;flex-direction:column;align-items:center;gap:8px;
}
.cat-tile svg{width:20px;height:20px;color:var(--text-2);transition:color .15s}
.cat-tile b{font-size:12.5px;font-weight:650;color:var(--ink)}
.cat-tile:hover{border-color:#C8D2DF;transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.cat-tile.on{border-color:var(--brand);background:var(--brand-50);box-shadow:0 0 0 1px var(--brand)}
.cat-tile.on svg{color:var(--brand)}
.urg-row{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
@media (max-width:760px){.urg-row{grid-template-columns:1fr}}
.urg{border:1px solid var(--border);border-radius:13px;background:#fff;padding:12px 13px;text-align:left;cursor:pointer;transition:all .15s}
.urg b{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:650;color:var(--ink)}
.urg b i{width:9px;height:9px;border-radius:50%;background:var(--green-dot);flex-shrink:0}
.urg span{display:block;font-size:11px;color:var(--text-3);margin-top:3px;line-height:1.4}
.urg.soon b i{background:var(--amber-dot)}
.urg.acute b i{background:var(--red-dot)}
.urg:hover{border-color:#C8D2DF}
.urg.on{border-color:var(--green-dot);background:var(--green-bg);box-shadow:0 0 0 1px var(--green-dot)}
.urg.soon.on{border-color:var(--amber-dot);background:var(--amber-bg);box-shadow:0 0 0 1px var(--amber-dot)}
.urg.acute.on{border-color:var(--red-dot);background:var(--red-bg);box-shadow:0 0 0 1px var(--red-dot)}
/* The four levels, one tile each, with the tone the priority chip uses:
   Lav grey, Mellem the brand, Høj amber (.soon), Akut red (.acute). */
.urg-row.four{grid-template-columns:repeat(4,minmax(0,1fr))}
.urg-row.four.compact{grid-template-columns:repeat(2,minmax(0,1fr))}
@media (max-width:760px){.urg-row.four{grid-template-columns:repeat(2,minmax(0,1fr))}}
.urg.low b i{background:var(--text-3)}
.urg.medium b i{background:var(--brand)}
.urg.low.on,.urg.medium.on{border-color:var(--brand);background:var(--brand-50);box-shadow:0 0 0 1px var(--brand)}
.urg-row.err .urg{border-color:var(--red)}
.done-hero{text-align:center;padding:34px 22px 30px}
.done-check{
  width:64px;height:64px;border-radius:50%;background:var(--green-dot);color:#fff;
  display:grid;place-items:center;margin:0 auto 18px;
  box-shadow:0 0 0 10px var(--green-bg);
  animation:popIn .45s cubic-bezier(.34,1.4,.5,1) both;
}
.done-check svg{width:30px;height:30px}
@keyframes popIn{from{transform:scale(.4);opacity:0}to{transform:none;opacity:1}}
.done-hero h2{font-family:var(--font-display);font-size:22px;font-weight:750;letter-spacing:-.02em;color:var(--ink)}
.done-hero .did{margin-top:7px;font-size:13px;color:var(--text-2)}
.done-next{margin:22px auto 0;max-width:430px;text-align:left;border:1px solid var(--border);border-radius:14px;background:#FBFCFD;padding:6px 16px}
.done-next .dn{display:flex;gap:11px;align-items:flex-start;padding:10px 0;font-size:12.5px;color:var(--text-2);line-height:1.5}
.done-next .dn + .dn{border-top:1px solid var(--border-2)}
.done-next .dn .n{width:22px;height:22px;border-radius:50%;background:var(--brand-50);color:var(--brand);font-size:11px;font-weight:750;display:grid;place-items:center;flex-shrink:0}
.done-next .dn b{color:var(--ink);font-weight:650}
.done-act{display:flex;gap:9px;justify-content:center;margin-top:22px;flex-wrap:wrap}
/* The photograph step on the poster's confirmation. Deliberately quieter than
   the primary action beneath it: the report is already filed, and this is an
   offer rather than an instruction. */
.qphoto{margin:18px auto 0;max-width:430px;text-align:center;border:1px dashed var(--border);border-radius:14px;padding:16px;background:#FBFCFD}
html.dark .qphoto{background:#141922}
.qphoto-h{font-size:12.5px;color:var(--text-2);line-height:1.5;margin-bottom:11px}
.qphoto .btn{width:100%;justify-content:center}
.qphoto-list{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-bottom:11px}
.qphoto-chip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;color:var(--green);background:var(--green-bg);border:1px solid var(--green-br);border-radius:999px;padding:3px 10px}
.qphoto-chip svg{width:11px;height:11px}
.qphoto-note{font-size:11.5px;color:var(--text-3);line-height:1.5;margin-top:8px}
.qphoto-note.err{color:var(--red)}
.qphoto-note svg{width:15px;height:15px;flex:none}
.cat-glyph{display:inline-flex;flex:none;color:var(--text-2)}
.cat-glyph svg{width:16px;height:16px}
.icon-pick{display:flex;flex-wrap:wrap;gap:6px}
.icon-pick .cbtn{width:38px;height:38px;color:var(--text-2)}
.cbtn:disabled{opacity:.35;cursor:default;transform:none}
.icon-pick .cbtn svg{width:18px;height:18px}
.icon-pick .cbtn.on{border-color:var(--brand);background:var(--brand-50);box-shadow:0 0 0 1px var(--brand);color:var(--brand)}

/* ---- the poster page (qr.html) ----
   The language button lives in the card's own header row rather than fixed
   over the page, where it floated across "Beskriv problemet" when scrolled. */
.qr-head{display:flex;align-items:center;gap:12px;margin-bottom:6px}
.qr-head .auth-logo{flex:1;min-width:0;margin-bottom:0}
.qr-head .logo-txt{min-width:0}
.qr-head .logo-txt b{overflow-wrap:anywhere}
.qr-head #langBtn{flex-shrink:0;border:1px solid var(--border);background:var(--card);height:34px}
.qr-skel{display:grid;gap:12px;padding:4px 0 8px}
.qr-skel i{display:block;height:14px;border-radius:7px;background:var(--border-2);animation:pulseSkel 1.2s ease-in-out infinite alternate}
.qr-skel i.big{height:44px;width:44px;border-radius:13px}
.qr-skel i.w60{width:60%}
.qr-skel i.tiles{height:150px;border-radius:14px}
@keyframes pulseSkel{from{opacity:.55}to{opacity:1}}
.qr-call{display:flex;gap:10px;align-items:flex-start;margin-top:12px;padding:12px 14px;border-radius:13px;border:1px solid var(--red-br);background:var(--red-bg);font-size:13px;line-height:1.5;color:var(--ink);text-align:left}
.qr-call svg{width:18px;height:18px;color:var(--red);flex-shrink:0;margin-top:1px}
.qr-call a{color:var(--red);font-weight:750;text-decoration:none;white-space:nowrap}
.qr-call a:hover{text-decoration:underline}
.qr-call.plain{border-color:var(--border);background:var(--bg)}
.qr-call.plain svg{color:var(--text-3)}
/* The plain box is a note, not an emergency: its link is a link, not the red
   bold of "ring nu" (the only way to follow a poster report read as a call). */
.qr-call.plain a{color:var(--link);font-weight:650;text-decoration:underline;text-underline-offset:2px}
.qr-call.plain .btn{display:flex;margin-top:8px}
.qr-call.plain .f-input{width:100%;margin-top:8px;font-size:12.5px}
.qr-privacy{margin-top:14px;font-size:12px;color:var(--text-3);line-height:1.6;text-align:left}
.qr-privacy summary{cursor:pointer;font-weight:650;color:var(--text-2);list-style:none;display:inline-flex;align-items:center;gap:6px;min-height:32px}
.qr-privacy summary::-webkit-details-marker{display:none}
.qr-privacy p{margin-top:6px}
.qr-privacy a{color:var(--brand);font-weight:600}
.qphoto-bar{height:6px;border-radius:3px;background:var(--border-2);overflow:hidden;margin-top:10px}
.qphoto-bar i{display:block;height:100%;background:var(--brand);border-radius:3px;transition:width .2s}
.report-hero{
  border-radius:var(--r-lg);padding:22px 24px;color:#fff;position:relative;overflow:hidden;
  background:linear-gradient(135deg,#12579F,#0A3765);
  box-shadow:0 14px 34px -16px rgba(10,55,101,.55);
}
.report-hero::after{content:"";position:absolute;right:-60px;top:-70px;width:230px;height:230px;border-radius:50%;background:rgba(255,255,255,.07)}
.report-hero h2{font-family:var(--font-display);font-size:20px;font-weight:750;letter-spacing:-.02em}
.report-hero p{font-size:13px;color:rgba(255,255,255,.82);margin-top:5px;max-width:440px;line-height:1.55}
.report-hero .btn{margin-top:16px;background:#fff;color:var(--brand);box-shadow:0 2px 8px rgba(0,0,0,.18)}
.report-hero .btn:hover{background:#F2F6FB;transform:translateY(-1px)}
.faq details{border:1px solid var(--border);border-radius:12px;background:#fff;margin-bottom:8px;overflow:hidden}
.faq summary{list-style:none;cursor:pointer;padding:12px 15px;font-size:13px;font-weight:650;color:var(--ink);display:flex;align-items:center;gap:9px}
.faq summary::-webkit-details-marker{display:none}
.faq summary svg{width:14px;height:14px;color:var(--text-3);margin-left:auto;flex-shrink:0;transition:transform .2s}
.faq details[open] summary svg{transform:rotate(180deg)}
.faq .fa{padding:0 15px 13px;font-size:12.5px;color:var(--text-2);line-height:1.6}

/* ============ Provider console ============ */
.clients-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px}
.client-card{
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);padding:16px 17px 14px;text-align:left;width:100%;cursor:pointer;
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s;
  display:flex;flex-direction:column;gap:12px;
}
.client-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:#D5DBE4}
.cc-top{display:flex;align-items:center;gap:11px}
.cmark{
  width:40px;height:40px;border-radius:12px;color:#fff;flex-shrink:0;
  display:grid;place-items:center;font-family:var(--font-display);font-weight:800;font-size:14px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2);
}
.cc-top b{display:block;font-size:14.5px;font-weight:700;color:var(--ink);font-family:var(--font-display);letter-spacing:-.01em}
.cc-top .dom{font-size:11.5px;color:var(--text-3)}
.cc-top .chip{margin-left:auto}
.cstats{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;border-top:1px solid var(--border-2);padding-top:11px}
.cstat b{display:block;font-family:var(--font-display);font-size:16px;font-weight:750;color:var(--ink);font-variant-numeric:normal}
.cstat span{font-size:10px;color:var(--text-3);font-weight:600;letter-spacing:.02em}
.cstat.warn b{color:#B26205}
.cc-note{font-size:11.5px;color:var(--text-2);background:#F7F8FA;border:1px solid var(--border-2);border-radius:9px;padding:7px 10px;display:flex;align-items:center;gap:7px;line-height:1.4}
.cc-note svg{width:13px;height:13px;color:var(--amber-dot);flex-shrink:0}
.g-pan{grid-template-columns:1.7fr 130px 1.3fr 90px 90px 110px 40px}
.mini-portal{
  border:1px solid var(--border);border-radius:14px;overflow:hidden;background:var(--bg);
  display:flex;height:236px;box-shadow:inset 0 1px 3px rgba(15,21,34,.05);
  --pv:#0E4A8C;
}
.mini-side{width:96px;background:#FBFBFC;border-right:1px solid var(--border-2);padding:9px 7px;display:flex;flex-direction:column;gap:3px;flex-shrink:0}
.mini-logo{display:flex;align-items:center;gap:5px;margin-bottom:7px}
.mini-mark{width:16px;height:16px;border-radius:5px;background:var(--pv);color:#fff;font-size:7px;font-weight:800;display:grid;place-items:center;flex-shrink:0}
.mini-name{font-size:7.5px;font-weight:700;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:62px}
.mini-nav{height:9px;border-radius:4px;background:#EDEFF3;margin:2px 1px}
.mini-nav.on{background:color-mix(in srgb,var(--pv) 16%, white)}
.mini-main{flex:1;padding:9px 10px;display:flex;flex-direction:column;gap:7px;min-width:0}
.mini-top{display:flex;gap:5px;align-items:center}
.mini-search{flex:1;height:11px;border-radius:5px;background:#fff;border:1px solid var(--border-2)}
.mini-btn{width:36px;height:11px;border-radius:5px;background:var(--pv)}
.mini-hello{height:10px;width:46%;border-radius:4px;background:#E3E6EB;margin-top:2px}
.mini-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:5px}
.mini-tile{height:34px;border-radius:6px;background:#fff;border:1px solid var(--border-2);border-left:2.5px solid var(--green-dot)}
.mini-tile.a{border-left-color:var(--amber-dot)}
.mini-tile.r{border-left-color:var(--red-dot)}
.mini-card{flex:1;border-radius:8px;background:#fff;border:1px solid var(--border-2);position:relative;overflow:hidden;min-height:36px}
.mini-card::before{content:"";position:absolute;top:0;left:0;right:0;height:2.5px;background:var(--pv)}
.swatches{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.swatch{
  width:32px;height:32px;border-radius:11px;cursor:pointer;position:relative;border:none;
  transition:transform .14s ease;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.25), 0 1px 3px rgba(15,21,34,.18);
}
.swatch:hover{transform:translateY(-2px) scale(1.05)}
.swatch.on::after{content:"";position:absolute;inset:-5px;border-radius:14px;border:2px solid var(--ink)}
.conn-hero{
  border:1px solid var(--green-br);border-radius:var(--r-lg);
  background:linear-gradient(180deg,#FCFFFD,#F0FAF4);box-shadow:var(--shadow-sm);
  padding:18px;display:flex;gap:14px;align-items:center;flex-wrap:wrap;
}
.conn-hero .cic{
  width:46px;height:46px;border-radius:14px;background:var(--green-dot);color:#fff;
  display:grid;place-items:center;flex-shrink:0;box-shadow:0 6px 16px -6px rgba(34,165,94,.6);
}
.conn-hero .cic svg{width:22px;height:22px}
.conn-hero b{display:block;font-family:var(--font-display);font-size:16px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
.conn-hero .cs{font-size:12.5px;color:var(--text-2);margin-top:2px}
.conn-hero .r{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}
.feed{padding:4px 18px 12px}
.feedline{display:flex;gap:11px;align-items:flex-start;padding:10px 0;font-size:12.5px;color:var(--text-2);width:100%;text-align:left;line-height:1.45}
.feedline + .feedline{border-top:1px solid var(--border-2)}
.feedline .fic{width:24px;height:24px;border-radius:8px;background:#EFF1F5;color:var(--text-2);display:grid;place-items:center;flex-shrink:0;margin-top:1px}
.feedline .fic svg{width:12px;height:12px}
.feedline .fic.g{background:var(--green-bg);color:var(--green)}
.feedline .fic.b{background:var(--brand-50);color:var(--brand)}
.feedline .fic.a{background:var(--amber-bg);color:var(--amber)}
.feedline b{color:var(--ink);font-weight:650}
.feedline time{margin-left:auto;font-size:11px;color:var(--text-3);white-space:nowrap;padding-top:2px;flex-shrink:0}
.check-item{display:flex;gap:10px;align-items:center;padding:8px 0;font-size:12.5px;color:var(--text-2)}
.check-item + .check-item{border-top:1px solid var(--border-2)}
.check-item .ck{width:20px;height:20px;border-radius:50%;flex-shrink:0;display:grid;place-items:center}
.check-item.done .ck{background:var(--green-dot);color:#fff}
.check-item.done span{color:var(--text-3);text-decoration:line-through}
.check-item:not(.done) .ck{border:2px solid #C9D0DA;color:transparent}
.check-item .ck svg{width:10px;height:10px}
.kv .v code{font-family:ui-monospace,SFMono-Regular,monospace;font-size:11px;background:#F2F3F6;border:1px solid var(--border);padding:2px 7px;border-radius:6px;color:var(--text-2)}
.domrow{display:flex;align-items:center;gap:0;max-width:360px}
.domrow .f-input{flex:1;border-radius:10px 0 0 10px;border-right:none}
.domrow .suffix{
  height:36px;display:flex;align-items:center;padding:0 12px;
  background:#F7F8FA;border:1px solid var(--border);border-radius:0 10px 10px 0;
  font-size:12.5px;color:var(--text-3);font-weight:600;white-space:nowrap;
}

/* ============ Logo upload (brand) ============ */
.logo-drop{display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.logo-drop .ld-txt{flex:1;min-width:130px}
.logo-drop .ld-txt b{display:block;font-size:12.5px;font-weight:650;color:var(--ink)}
.logo-drop .ld-txt span{font-size:11px;color:var(--text-3);line-height:1.4;display:block;margin-top:1px}
.cmark img{width:74%;height:74%;object-fit:contain;display:block}
.cmark.haslogo{background:#fff!important;border:1px solid var(--border)}
.mini-mark img{width:82%;height:82%;object-fit:contain;display:block}
.mini-mark.haslogo{background:#fff;border:1px solid var(--border-2)}
.logo-mark img{width:74%;height:74%;object-fit:contain;display:block}
.logo-mark.haslogo{background:#fff!important;border:1px solid var(--border);box-shadow:none}

/* ============ Standalone helpdesk ============ */
.g-tix{grid-template-columns:84px 1.2fr 1.7fr 160px 90px 120px 110px}
.g-esager{grid-template-columns:86px 1.6fr 1fr 170px 96px}
.sla-ok{color:var(--green);font-weight:650;font-size:12px}
.sla-warn{color:var(--amber);font-weight:650;font-size:12px}
.sla-breach{color:var(--red);font-weight:700;font-size:12px}
.sr-only{
  position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;
  overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important;
}
.sla-summary{display:flex;flex-wrap:wrap;gap:5px 10px;margin-top:5px;line-height:1.35}
.sla-mini{font-size:10.5px;color:var(--text-3);font-weight:550}
.sla-mini b{font-weight:700;color:inherit}
.sla-mini.met{color:var(--green)}
.sla-mini.countdown{color:var(--brand)}
.sla-mini.paused{color:var(--amber)}
/* "Something happened here you have not seen." Sits beside the reference in a
   row, which is the first thing the eye lands on when scanning a list. */
.unseen-dot{display:inline-block;width:7px;height:7px;border-radius:50%;
  background:var(--brand);margin-right:6px;vertical-align:middle;flex:none}

.sla-mini.at_risk{color:var(--amber);font-weight:700}
.sla-mini.breach{color:var(--red);font-weight:700}
.sla-card .rc-b{display:flex;flex-direction:column;gap:10px}
.sla-detail{display:grid;grid-template-columns:9px 1fr;gap:9px;align-items:start}
.sla-detail .sla-dot{width:8px;height:8px;border-radius:50%;background:var(--brand);margin-top:4px}
.sla-detail.met .sla-dot{background:var(--green-dot)}
.sla-detail.paused .sla-dot{background:var(--amber-dot)}
.sla-detail.at_risk .sla-dot{background:var(--amber-dot)}
.sla-detail.breach .sla-dot{background:var(--red-dot)}
.sla-detail > span:last-child{min-width:0}
.sla-detail b{display:block;font-size:11.5px;color:var(--ink)}
.sla-detail > span:last-child > span{display:block;font-size:11px;color:var(--text-2);line-height:1.45;margin-top:2px}
.sla-detail.breach b,.sla-detail.breach > span:last-child > span{color:var(--red)}
.sla-detail.paused b{color:var(--amber)}
.sla-note{font-size:10.5px;color:var(--text-3);line-height:1.5;padding-top:8px;border-top:1px solid var(--border-2)}
/* 170px for the status, as on "Mine sager" below: at 160 the store's overview
   cut "Venter på godkendelse" to "Venter på godkend…" (W-15). */
.employee-home-case{grid-template-columns:86px minmax(0,1fr) 170px 96px}
.employee-case-list-row{grid-template-columns:86px minmax(0,1.6fr) minmax(110px,1fr) 170px 96px}
.itabs{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 8px 44px}
.itab{height:26px;padding:0 11px;border-radius:8px;font-size:11.5px;font-weight:650;border:1px solid var(--border);background:#fff;color:var(--text-2);transition:all .13s}
.itab.on{background:var(--ink);border-color:var(--ink);color:#fff}
.itab.on.notetab{background:var(--amber-dot);border-color:var(--amber-dot)}
.bubble.internal{background:var(--amber-bg);border-color:var(--amber-br)}
.int-label{font-size:9.5px;font-weight:750;letter-spacing:.06em;text-transform:uppercase;color:var(--amber);display:block;margin-bottom:3px}
.of-line{display:flex;gap:8px;margin-bottom:8px}
.of-line .f-input{flex:1;min-width:0}
.of-line .f-input.amt2{width:110px;flex:none;text-align:right;font-variant-numeric:tabular-nums}
.komp{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:6px;font-size:10.5px;font-weight:650;background:var(--brand-50);color:var(--brand);border:1px solid var(--brand-100);margin:1px 3px 1px 0}

/* ============ v1-full additions (CSAT, notif-matrix, compliance, dupe, AI) ============ */
.stars{display:flex;gap:2px}
.star{font-size:22px;line-height:1;color:#C9D0DA;cursor:pointer;transition:transform .12s,color .12s;background:none;border:none;padding:2px}
.star:hover{transform:scale(1.18)}
.star.on{color:var(--amber-dot)}
.csat-box{border:1px solid var(--border);border-radius:14px;background:var(--card);padding:12px 16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-left:44px}
.csat-box b{font-size:13px;color:var(--ink)}
.csat-box .done{font-size:12.5px;color:var(--green);font-weight:650}
.nchip{display:inline-flex;align-items:center;height:24px;padding:0 10px;border-radius:999px;border:1px solid var(--border);background:var(--card);font-size:11px;font-weight:650;color:var(--text-3);cursor:pointer;transition:all .13s}
.nchip.on{background:var(--green-bg);border-color:var(--green-br);color:var(--green)}
.nchips{display:flex;gap:6px;flex-shrink:0}
.g-comp{grid-template-columns:1.4fr 1fr 1fr 1fr}
.g-audit{grid-template-columns:120px 1fr 1.8fr 110px 110px}
.g-plan{grid-template-columns:1.7fr 110px 1fr 120px 110px}
.dupe-warn{margin:10px 0 4px;display:flex;gap:10px;align-items:center;font-size:12.5px;color:var(--amber);font-weight:600;background:var(--amber-bg);border:1px solid var(--amber-br);padding:10px 13px;border-radius:11px;flex-wrap:wrap;line-height:1.45}
.dupe-warn svg{width:15px;height:15px;flex-shrink:0}
.dupe-warn .da{margin-left:auto;display:flex;gap:8px;flex-shrink:0}
.aibtn{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:8px;font-size:11.5px;font-weight:650;border:1px solid var(--brand-100);background:var(--brand-50);color:var(--brand);cursor:pointer;transition:all .13s;white-space:nowrap}
/* Its icon had no size of its own (M-06): beside "Skabelon" it was squeezed
   to nothing, and beside "Canned reply" it took 31px and broke the label
   over two lines. The size a small button's icon has. */
.aibtn svg{width:13px;height:13px;flex-shrink:0}
.aibtn:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.budgetline{margin:10px 18px 0;font-size:11.5px;color:var(--text-2)}
.budgetline b{color:var(--ink)}
.budgetline .bar-track{margin-top:5px;height:6px}
/* CapEx/OpEx kontering */
.capexline{margin:12px 18px 0;display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:10px 12px}
.cx-l{display:flex;align-items:center;gap:9px;min-width:0}
.cx-l>div{display:flex;flex-direction:column;min-width:0}
.cx-l b{font-size:12.5px;color:var(--ink);font-weight:650}
.cx-l>div>span{font-size:11px;color:var(--text-3);line-height:1.4}
.cx-ic{color:var(--brand);flex-shrink:0;display:flex}
.cx-ic svg{width:16px;height:16px;display:block}
.cx-seg{display:inline-flex;background:var(--card);border:1px solid var(--border);border-radius:9px;padding:3px;gap:3px;flex-shrink:0}
.cx-opt{border:none;background:none;font:inherit;font-size:12px;font-weight:600;color:var(--text-2);padding:6px 12px;border-radius:7px;cursor:pointer;white-space:nowrap}
.cx-opt.on{background:var(--brand);color:#fff}
.cx-opt.cap.on{background:var(--amber);color:#fff}
html.dark .cx-opt.on{color:#0F1319}
.cx-inline{margin:10px 18px 0;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.cx-check{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600;color:var(--ink);cursor:pointer}
.cx-check input{width:16px;height:16px;accent-color:var(--amber);cursor:pointer}
.cx-hint{font-size:11px;color:var(--text-3)}
/* ⚠️ USED NINETEEN TIMES IN fogidesk-chrome.js AND STYLED NOWHERE UNTIL NOW.
   Every "Loading…", every empty bell, every "Nothing matches", every secondary
   line under a search result and under a session was written as secondary text
   and rendered at full weight against the body colour. Nothing looked broken,
   which is why it survived: it looked like a design that simply had no
   de-emphasis. Found because check.php asserts that a class the JS TOGGLES is
   one a stylesheet really styles, and this was the first code to toggle it. */
.muted{color:var(--text-3)}
/* buyer console: tabs, tender bids, segmented control, category chips, invite list */
.tabs{display:flex;gap:7px;margin-bottom:14px;flex-wrap:wrap}
.tab{border:1px solid var(--border);background:var(--card);color:var(--text-2);font:inherit;font-size:12.5px;font-weight:600;padding:7px 14px;border-radius:9px;cursor:pointer}
.tab.on{background:var(--ink);color:var(--card);border-color:var(--ink)}
html.dark .tab.on{color:#0F1319}
.m-act{display:flex;gap:9px;margin-top:16px;flex-wrap:wrap}
.bidgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;padding:14px 16px 18px}
.bidcard{border:1px solid var(--border);border-radius:14px;padding:14px;display:flex;flex-direction:column;gap:8px;background:var(--card)}
.bidcard.best{border-color:var(--green-br);background:var(--green-bg)}
.bidcard.pending{opacity:.92;border-style:dashed}
.bc-top{display:flex;align-items:center;gap:10px}
.bc-id{min-width:0;flex:1}
.bc-id b{display:block;font-size:13px;color:var(--ink);font-weight:650;line-height:1.2}
.bc-id span{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-3)}
.bc-flag{font-size:10px;font-weight:700;color:var(--green);background:var(--card);border:1px solid var(--green-br);padding:3px 7px;border-radius:20px;white-space:nowrap}
.bc-price{font-family:"Schibsted Grotesk",Inter,sans-serif;font-size:26px;font-weight:700;color:var(--ink);letter-spacing:-.01em;line-height:1}
.bc-price small{font-size:13px;font-weight:600;color:var(--text-3)}
.bc-note{font-size:12px;color:var(--text-2);line-height:1.5}
.bc-at{font-size:11px;color:var(--text-3)}
.bc-award{width:100%;justify-content:center;margin-top:2px}
.bc-wait{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--text-3);padding:6px 0}
.bc-wait svg{width:15px;height:15px;flex-shrink:0}
.rate{display:inline-flex;align-items:center;gap:3px;font-size:11.5px;font-weight:650;color:var(--amber)}
.rate svg{width:12px;height:12px}
.seg2{display:inline-flex;gap:4px;background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:4px}
.seg2b{border:none;background:none;font:inherit;font-size:12.5px;font-weight:600;color:var(--text-2);padding:7px 14px;border-radius:7px;cursor:pointer}
.seg2b.on{background:var(--card);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.06)}
.chipwrap{display:flex;flex-wrap:wrap;gap:7px}
.pchip{border:1px solid var(--border);background:var(--card);color:var(--text-2);font:inherit;font-size:12px;font-weight:600;padding:6px 12px;border-radius:20px;cursor:pointer}
.pchip.on{background:var(--brand);color:#fff;border-color:var(--brand)}
html.dark .pchip.on{color:#0F1319}
.invlist{display:flex;flex-direction:column;gap:2px;max-height:280px;overflow:auto;margin-bottom:4px}
.invrow{display:flex;align-items:center;gap:10px;padding:9px 8px;border-radius:10px;cursor:pointer}
.invrow:hover{background:var(--bg)}
.invrow input{width:16px;height:16px;accent-color:var(--brand);flex-shrink:0}
.budget-copy-row .tt{display:flex;min-width:0;flex-direction:column;gap:2px}
.budget-copy-row .tt b{font-size:13px;line-height:1.25;color:var(--ink)}
.budget-copy-row .tt span{font-size:11.5px;line-height:1.4;color:var(--text-3)}
.budget-start-actions{gap:12px}
.approval-actions{display:flex;align-items:center;justify-content:flex-end;gap:6px;white-space:nowrap}
/* add-on hero (client "Leverandører" · own-subcontractors upsell) */
.addon-hero{display:flex;align-items:center;gap:14px;padding:14px 16px;border:1px solid var(--green-br);background:var(--green-bg);border-radius:14px;margin-bottom:14px}
.ah-ic{width:38px;height:38px;border-radius:11px;background:var(--card);display:flex;align-items:center;justify-content:center;color:var(--green);flex-shrink:0}
.ah-ic svg{width:20px;height:20px}
.ah-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ah-txt b{font-size:13px;color:var(--ink);font-weight:650}
.ah-txt>span{font-size:12px;color:var(--text-2);line-height:1.5}
/* accounting connect cards (standalone · Regnskabsintegration) */
.acct-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px;padding:14px 18px 18px}
.acct-card{border:1px solid var(--border);border-radius:14px;padding:14px;display:flex;flex-direction:column;gap:10px;background:var(--card)}
.acct-top{display:flex;align-items:center;gap:11px}
.acct-logo{width:40px;height:40px;border-radius:11px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:15px;flex-shrink:0;letter-spacing:-.02em}
.acct-id b{display:block;font-size:13.5px;color:var(--ink);font-weight:650;line-height:1.15}
.acct-id span{font-size:11px;color:var(--text-3)}
.acct-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:2px}
.acct-status{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;color:var(--text-3)}
.acct-status.on{color:var(--green)}
.acct-status i{width:7px;height:7px;border-radius:50%;background:currentColor;display:inline-block}
/* filter bar (compact · sits under the toolbar/tabs of a list card) */
.filterbar{display:flex;align-items:center;gap:7px;padding:10px 14px;flex-wrap:wrap;border-top:1px solid var(--border-2)}
.tbl>.filterbar:first-child,.filterbar.flush{border-top:none}
.filterbar .ficon{display:inline-flex;color:var(--text-3);flex-shrink:0;margin-right:1px}
.filterbar .ficon svg{width:14px;height:14px;display:block}
.filterbar .fbl{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-3);margin-right:1px}
.fsel{position:relative;display:inline-flex}
.fsel select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  height:31px;background:var(--card);border:1px solid var(--border);border-radius:8px;
  font:inherit;font-size:12px;font-weight:600;color:var(--text-2);
  padding:0 27px 0 11px;cursor:pointer;max-width:180px;
  box-shadow:var(--shadow-sm);transition:border-color .14s,color .14s,background .14s;
}
.fsel select:hover{border-color:#CBD6E4;color:var(--ink)}
.fsel select:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(14,74,140,.1)}
.fsel.act select{border-color:var(--brand);color:var(--brand);background:var(--brand-50);font-weight:650}
/* ⚠️ `.act` IS ALSO THE ACTIVITY ROW (above: width:100%, padding, a grid and a
   border between two of them), so every filter that was switched on took a
   whole line of the filter bar, and two side by side got a rule between them.
   Seen on People once state and region were chosen together (WP36). */
.fsel.act{width:auto;padding:0;border-radius:0;cursor:auto}
.fsel.act + .fsel.act{border-top:0}
.fsel.act:hover{background:none}
.fsel::after{content:"";position:absolute;right:11px;top:50%;transform:translateY(-70%) rotate(45deg);width:5px;height:5px;border-right:1.7px solid var(--text-3);border-bottom:1.7px solid var(--text-3);pointer-events:none;transition:border-color .14s}
.fsel.act::after{border-color:var(--brand)}
html.dark .fsel select:hover{border-color:#3A4556}
html.dark .fsel.act select{background:rgba(91,150,224,.14)}
html.dark .fsel select:focus{box-shadow:0 0 0 3px rgba(91,150,224,.12)}
/* The filter row's box to type in (a name, an invoice number, a date): the
   dropdown's own box and type, without its arrow (W-11). */
.ftext{display:inline-flex;max-width:100%}
.ftext input{
  height:31px;background:var(--card);border:1px solid var(--border);border-radius:8px;
  font:inherit;font-size:12px;font-weight:600;color:var(--text-2);
  padding:0 11px;max-width:100%;outline:0;
  box-shadow:var(--shadow-sm);transition:border-color .14s,color .14s,background .14s;
}
.ftext input::placeholder{color:var(--text-3);font-weight:600;opacity:1}
.ftext input:hover{border-color:#CBD6E4}
.ftext input:focus{border-color:var(--brand);box-shadow:0 0 0 3px rgba(14,74,140,.1)}
.ftext.act input{border-color:var(--brand);color:var(--brand);background:var(--brand-50);font-weight:650}
html.dark .ftext input{color-scheme:dark}
html.dark .ftext input:hover{border-color:#3A4556}
html.dark .ftext.act input{background:rgba(91,150,224,.14)}
/* The filter row's switch: a tick and its words in the row's own type ("Vis
   arkiverede" on the desk's Serviceplaner and on a customer's plans, Q-05). */
.fcheck{display:inline-flex;align-items:center;gap:6px;min-height:31px;padding:0 4px;font-size:12px;font-weight:600;color:var(--text-2);cursor:pointer;white-space:nowrap}
.fcheck input{width:15px;height:15px;margin:0;accent-color:var(--brand);cursor:pointer;flex-shrink:0}
html.dark .ftext input:focus{box-shadow:0 0 0 3px rgba(91,150,224,.12)}
/* toggle-style filter chip (e.g. tags, quick booleans) */
.fchip{display:inline-flex;align-items:center;gap:6px;height:31px;padding:0 11px;border-radius:8px;border:1px solid var(--border);background:var(--card);box-shadow:var(--shadow-sm);font-size:12px;font-weight:600;color:var(--text-2);cursor:pointer;transition:border-color .14s,color .14s,background .14s;white-space:nowrap}
.fchip:hover{border-color:#CBD6E4;color:var(--ink)}
.fchip .fdot{width:8px;height:8px;border-radius:3px;flex-shrink:0}
.fchip.act{border-color:var(--brand);color:var(--brand);background:var(--brand-50)}
html.dark .fchip:hover{border-color:#3A4556}
html.dark .fchip.act{background:rgba(91,150,224,.14)}
/* The group Rapporter is narrowed to, beside its customer (F-04): a long
   name is cut with an ellipsis rather than pushing the row wide, and the
   cross says the chip takes the group away. The 100% is the filter row's,
   which carries min-width:0 in PAGES.reports: without it the row was as wide
   as the chip, and a path of 150 characters ran some 270px past the head at
   768 and 1024px, uncut (the check of wave 14b). */
.fchip.fgroup{max-width:100%}
.fchip.fgroup .fl{overflow:hidden;text-overflow:ellipsis;min-width:0}
.fchip .fx{display:inline-flex;margin-right:-3px}
.fchip .fx svg{width:12px;height:12px}
.fclear{border:none;background:none;font:inherit;font-size:12px;font-weight:650;color:var(--brand);cursor:pointer;padding:6px 9px;border-radius:7px}
.fclear:hover{background:var(--brand-50)}
html.dark .fclear:hover{background:rgba(91,150,224,.14)}
/* A day in the filter row (WP31): the two days head office's list is
   reported between, looking like the selects beside them. */
.fdate{display:inline-flex;align-items:center;gap:6px;height:31px;padding:0 4px 0 10px;border:1px solid var(--border);border-radius:8px;background:var(--card);box-shadow:var(--shadow-sm)}
.fdate .fbl{margin:0}
.fdate input{border:0;background:transparent;font:inherit;font-size:12px;font-weight:600;color:var(--text-2);outline:0;height:29px}
.fdate.act{border-color:var(--brand);background:var(--brand-50)}
.fdate.act input{color:var(--brand)}
html.dark .fdate.act{background:rgba(91,150,224,.14)}
html.dark .fdate input{color-scheme:dark}
/* The deadline column on a case list: when, and how it stands; red once missed. */
.trow .dl{display:flex;flex-direction:column;line-height:1.3;min-width:0}
.trow .dl b{font-size:12.5px;font-weight:650;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trow .dl span{font-size:11px;color:var(--text-3)}
.trow .dl.breach b,.trow .dl.breach span{color:var(--red)}
.trow .dl.at_risk span,.trow .dl.paused span{color:var(--amber)}
.trow .dl.met span{color:var(--green)}
.fcount{margin-left:auto;font-size:11.5px;font-weight:600;color:var(--text-3);font-variant-numeric:tabular-nums;padding-left:6px;white-space:nowrap}

/* ============ Dark theme (html.dark) ============ */
html.dark{
  --brand:#5B96E0; --brand-600:#6BA3E8; --brand-700:#7FB1EE;
  --brand-100:#1D3352; --brand-50:#152840;
  /* ⚠️ THE BRAND IS NOT A TEXT COLOUR ON A DARK CARD. FogiDeskBrand writes the
     workspace's own --brand onto the page in both themes, over the lighter
     blue above, so a link drawn in it was dark blue on near-black: 1.6:1 for
     "Glemt adgangskode?" on the sign-in card. Mixed half way to white it
     passes for any workspace colour, and a colour that was light already
     only gets lighter. */
  --link:color-mix(in srgb,var(--brand) 50%,#fff);
  --ink:#F1F5FA; --text:#D8DFE9; --text-2:#9AA6B7; --text-3:#8A96A8; /* audit: kontrastløft i mørkt tema */
  --bg:#0F1319; --card:#171C24; --border:#252D39; --border-2:#1E2530;
  --green:#5BD48E; --green-bg:#0F2818; --green-br:#1E4A2E;
  --amber:#E8B04B; --amber-bg:#2A2110; --amber-br:#4A3A17;
  --red:#F07566; --red-bg:#2C1614; --red-br:#543029;
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --shadow-md:0 1px 2px rgba(0,0,0,.4), 0 10px 30px -14px rgba(0,0,0,.6);
  --shadow-lg:0 2px 4px rgba(0,0,0,.5), 0 24px 60px -24px rgba(0,0,0,.8);
}
/* ⚠️ ON A DARK GROUND THE BRAND IS TWO COLOURS, NOT ONE.
   A workspace's colour is chosen to carry WHITE text (Support\Brand refuses
   anything lighter), and fogidesk-brand.js writes it onto <html> inline, where
   it outranks the light accent the block above sets. So everything that wears
   the brand as a TEXT colour, the active menu item, a blue status chip, a
   link, "Sæt et tidspunkt", a visit time on the planning board, was dark blue
   on dark navy: 1.7:1 where 4.5 is asked for.

   From <body> down, --brand is therefore the colour lifted toward white. 45%
   keeps every channel above 140, which is at least 5:1 on the card for any
   colour the picker allows, black included. That is what the rules that use it
   as text, as a dot or as an outline need, and it is why the "on" states below
   may go on carrying dark text. The few surfaces that put white text ON the
   brand, or brand text on a white button, keep the colour itself through
   --brand-solid.

   Only where a workspace colour was written: without one (the operator
   console, a sign-in page before its portal is known) the accent above already
   is the light one. And only where color-mix exists; elsewhere nothing moves. */
html.dark{--brand-solid:var(--brand)}
@supports (color:color-mix(in srgb,red,blue)){
  html.dark[style*="--brand:"]{--brand-ink:color-mix(in srgb,var(--brand) 45%,#fff)}
  html.dark[style*="--brand:"] body{--brand:var(--brand-ink)}
}
html.dark .logo-mark{background:linear-gradient(145deg,var(--brand-solid),var(--brand-700))}
html.dark .composer .send{background:var(--brand-solid)}
html.dark .report-hero .btn{color:var(--brand-solid)}
html.dark .rev-note{color:var(--brand)}
/* A link nobody styled is the browser's own #0000EE, which is unreadable here.
   :where() so that every rule that does colour a link still wins. */
:where(html.dark) a{color:var(--brand)}
html.dark body{background:var(--bg)}
html.dark .side{background:#12161E}
html.dark .nav-item:hover,html.dark .side-user:hover{background:#1B212C}
html.dark .topbar{background:rgba(15,19,25,.86)}
html.dark .search:hover{background:#1B212C;border-color:#334052}
html.dark .search kbd{background:#12161E;border-color:var(--border)}
/* The selected tab is a light fill with dark text. A dark-theme background for
   the tab itself must never outrank .pill.on or .itab.on: `html.dark .pill
   {background:#171C24}` did, and "Åbne" was dark text on a dark fill, 1.1:1. */
html.dark .pill.on{color:#0F1319}
html.dark .itab:not(.on){background:#171C24}
html.dark .itab.on{color:#0F1319}
html.dark .itab.on.notetab{color:#fff}
html.dark .sw-btn{color:#0F1319}
html.dark .store{background:#171C24}
html.dark .store.amber{background:#221D11}
html.dark .store.amber .st{color:var(--amber)}
html.dark .store.red{background:#251512}
html.dark .store.grey{background:#14181E}
html.dark .store.quiet{background:#1C1A14}
html.dark .trow-h{background:#131820}
html.dark button.trow:hover{background:#1B212C}
html.dark .t-search{background:#12161E}
html.dark .t-search:focus-within{background:#171C24;border-color:#33507A;box-shadow:0 0 0 3px rgba(91,150,224,.12)}
html.dark .f-input{background:#12161E;border-color:var(--border);color:var(--text)}
html.dark .f-input:focus{border-color:#33507A;box-shadow:0 0 0 3px rgba(91,150,224,.12)}
html.dark .composer{background:#171C24}
html.dark .composer:focus-within{border-color:#33507A;box-shadow:0 0 0 3px rgba(91,150,224,.12)}
html.dark .composer input{color:var(--text)}
html.dark .revision-box textarea{background:#12161E;color:var(--text);border-color:var(--border)}
html.dark .tgl{background:#2A3240}
html.dark .radio-pill,html.dark .cat-tile,html.dark .urg,html.dark .faq details{background:#171C24}
html.dark .cat-tile:hover,html.dark .radio-pill:hover,html.dark .urg:hover{border-color:#3A455699}
html.dark .appr-card{background:linear-gradient(180deg,#241D0E,#1E180B)}
html.dark .appr-empty{background:#141922}
html.dark .offer{background:linear-gradient(180deg,#171C24,#151E2C)}
html.dark .cmd{background:rgba(23,28,36,.97);border-color:rgba(255,255,255,.06)}
html.dark .cmd-in input{color:var(--ink)}
html.dark .citem .ci{background:#202734;border-color:var(--border)}
html.dark .citem.sel{background:var(--brand-50)}
html.dark .toast{background:#EAF0F7;color:#0F1319}
html.dark .toast.ask button:not(.quiet){background:#0F1319;color:#EAF0F7}
html.dark .proto{background:rgba(23,28,36,.85);border-color:var(--border)}
html.dark .doc .dic,html.dark .rolechip,html.dark .case-id,html.dark .step .ic,html.dark .sysline .sic{background:#202734;border-color:var(--border)}
html.dark .chip.gray{background:#202734}
html.dark .step .ic{border-color:#202734}
html.dark .step.done .ic{background:var(--green-dot);border-color:var(--green-dot)}
html.dark .step.cur .ic{background:#171C24}
html.dark .tag.med{background:#3A2E12;color:#E8B04B}
html.dark .tag.hoj{background:#3A211A;color:#F08A66}
html.dark .tag.lav{background:#202734;color:var(--text-2)}
html.dark .bar-track{background:#222938}
html.dark .hi::before{background:#171C24}
html.dark .hi.ok::before{background:var(--green-dot)}
/* The words on the small outline buttons are the brand colour, and on the
   dark card the brand is the workspace's own solid colour (fogidesk-brand.js
   writes it over the theme's): "Luk som…" read 1.94:1. A light tint of the
   same brand reads on the card whatever colour the workspace chose; the plain
   colour before it is for a browser without color-mix. The icon picker keeps
   its own grey. */
html.dark .cbtn{background:#171C24;color:#9DBEE6;color:color-mix(in srgb,var(--brand) 42%,#fff)}
html.dark .cbtn:hover{background:var(--brand-50)}
html.dark .icon-pick .cbtn:not(.on){color:var(--text-2)}
html.dark .icon-pick .cbtn.on{color:#9DBEE6;color:color-mix(in srgb,var(--brand) 42%,#fff)}
html.dark .conn-hero{background:linear-gradient(180deg,#12251A,#0F2016)}
html.dark .cc-note{background:#1A202B}
html.dark .kpi.k-red{background:linear-gradient(180deg,#171C24,#241517)}
html.dark .demo-strip a{background:#171C24}
html.dark .demo-strip a:hover{border-color:#3A4556}
html.dark .done-next{background:#141922}
html.dark .domrow .suffix{background:#1A202B}
html.dark .feedline .fic{background:#202734}
html.dark .btn-ghost{background:#1B212C;border-color:var(--border);color:var(--text)}
html.dark .btn-ghost:hover{background:#222938;border-color:#3A4556}
html.dark .btn-danger{background:#1B212C;border-color:var(--border)}
html.dark .btn-danger:hover{background:var(--red-bg);border-color:var(--red-br)}
/* The primary button is the brand on the dark theme too (audit F383): two blue
   literals here threw every customer's own colour away the moment the theme
   flipped. */
html.dark .btn-primary{background:var(--brand-solid)}
html.dark .btn-primary:hover{background:var(--brand-600)}
html.dark .icon-btn:hover{background:#1B212C;border-color:var(--border)}
html.dark .back:hover{background:#1B212C}
html.dark .m-x:not(.btn):hover{background:#1B212C}
html.dark .csat-box,html.dark .nchip{background:#171C24}
html.dark .nchip.on{background:var(--green-bg)}
/* An empty star is something to press, so it is seen: #3A4556 was 1.76:1
   on the card, five dents in the dark (W-09). 3.5:1 now, still well under
   the amber of a star that has been given. */
html.dark .star{color:#667386}
html.dark .star.on{color:var(--amber-dot)}
html.dark ::selection{background:#2A4A73}
html.dark .auth-wrap{background:radial-gradient(52% 44% at 10% 0%, rgba(91,150,224,.10), transparent 60%),radial-gradient(44% 40% at 100% 100%, rgba(34,165,94,.06), transparent 60%),var(--bg)}
/* the mini portal preview stays LIGHT on purpose: it previews the customer's portal */

/* ============ Responsive pass ============ */
.icon-btn.menu{display:none}
.scrim{position:fixed;inset:0;background:rgba(15,21,34,.42);z-index:195;opacity:0;pointer-events:none;transition:opacity .2s}
.scrim.show{opacity:1;pointer-events:auto}

@media (max-width:920px){
  .side{
    position:fixed;left:0;top:0;bottom:0;height:100dvh;z-index:220;
    width:min(280px,84vw);
    transform:translateX(-105%);
    transition:transform .28s cubic-bezier(.22,.9,.3,1);
    box-shadow:none;
  }
  .side.open{transform:none;box-shadow:var(--shadow-lg)}
  /* The page behind the drawer must not scroll under it. */
  body.nav-open{overflow:hidden}
  .icon-btn.menu{display:grid}
  .topbar{padding:0 12px;gap:8px}
  .content{padding:18px 14px 96px}
  .search{width:auto;flex:1;min-width:40px;padding:0 12px}
  .search kbd{display:none}
  .search .ph{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}
/* ⚠️ ON A PHONE THE SEARCH BOX SAID "S…" (W-38). The pill shares what is left
   of the top bar with the spacer beside it: some 20px for its words at 390 in
   the supplier console, none in the others, and a sliver in all five at 430.
   No phone held upright has room for "Søg i jeres opgaver" next to the menu,
   the language, the theme, the bell and the avatar, so there the pill is the
   magnifier alone, the size of the buttons beside it. The button keeps its
   name for a screen reader (aria-label), and the dialog it opens says what
   is searched. */
@media (max-width:480px){
  .search{flex:none;width:44px;padding:0;justify-content:center}
  .search .ph{display:none}
}
/* And at its fullest (menu, search, "Ny sag", language, theme, bell, avatar)
   the bar is 373px wide where a finger sets the size of the buttons, and a
   common phone is 360: the avatar ended one pixel past the screen, so every
   page could be pushed sideways. Under 374px its items stand 6px apart,
   which makes it 359. */
@media (max-width:373px){
  .topbar{gap:6px}
}

@media (max-width:820px){
  /* tables: keep the essentials, drop secondary columns */
  .g-sager{grid-template-columns:76px 1.5fr 140px}
  .g-sager > :nth-child(3),.g-sager > :nth-child(4),.g-sager > :nth-child(6),.g-sager > :nth-child(7){display:none}
  .g-fakt{grid-template-columns:88px 1fr 92px 104px}
  .g-fakt > :nth-child(2),.g-fakt > :nth-child(4){display:none}
  .g-brugere{grid-template-columns:2fr 1fr 40px}
  .g-brugere > :nth-child(3),.g-brugere > :nth-child(4){display:none}
  .g-afd{grid-template-columns:1.6fr 118px 40px}
  .g-afd > :nth-child(3),.g-afd > :nth-child(4),.g-afd > :nth-child(5){display:none}
  .g-pan{grid-template-columns:1.7fr 118px 90px 40px}
  .g-pan > :nth-child(3),.g-pan > :nth-child(4),.g-pan > :nth-child(5){display:none}
  .g-tix{grid-template-columns:80px 1.6fr 150px}
  .g-tix > :nth-child(2),.g-tix > :nth-child(5),.g-tix > :nth-child(6),.g-tix > :nth-child(7){display:none}
  .g-esager{grid-template-columns:80px 1.5fr 150px}
  .g-esager > :nth-child(3),.g-esager > :nth-child(5){display:none}
  .g-comp{grid-template-columns:1.4fr 1fr}
  .g-comp > :nth-child(3),.g-comp > :nth-child(4){display:none}
  .g-audit{grid-template-columns:110px 1.6fr}
  .g-audit > :nth-child(2),.g-audit > :nth-child(4),.g-audit > :nth-child(5){display:none}
  .g-plan{grid-template-columns:1.6fr 120px}
  .g-plan > :nth-child(2),.g-plan > :nth-child(3),.g-plan > :nth-child(5){display:none}
}

@media (max-width:640px){
  .kpis{grid-template-columns:repeat(2,1fr)!important;gap:10px;margin-bottom:16px}
  .kpi{padding:13px 14px 12px}
  .kpi .val{font-size:25px}
  .kpi .val.sum{--max:25px}
  .page-head{flex-direction:column;align-items:flex-start;gap:10px;margin-bottom:16px}
  /* A stacked column item is sized to its content, and a subtitle holding one
     long token (the guide's "…portalen på carlras.fogidesk.com") made the head
     2px wider than a 375px phone. It may break inside the word instead. */
  .page-head > *{max-width:100%;min-width:0}
  .page-head .sub{overflow-wrap:anywhere}
  /* Two buttons side by side ("Udskriv hele vejledningen" and "Udskriv / gem
     som PDF") are wider than a phone; the second goes under the first. */
  .page-head .actions{flex-wrap:wrap}
  .page-head h1{font-size:22px}
  .case-head h1{font-size:19px}
  .topbar .btn-primary .bl{display:none}
  .topbar .btn-primary{padding:0 12px}
  .f-2col{grid-template-columns:1fr}
  .stores{grid-template-columns:repeat(auto-fill,minmax(142px,1fr));gap:8px;padding:12px 12px 14px}
  .clients-grid{grid-template-columns:1fr}
  .split2{gap:12px}
  .set-grid{gap:12px}
  .auth-card{padding:24px 20px 20px}
  .auth-card.wide{padding:22px 16px 18px}
  .cat-grid{grid-template-columns:repeat(2,1fr)}
  .report-hero{padding:18px 18px 20px}
  .stepper{padding:13px 10px 11px}
  .step{min-width:76px}
  .thread .ev .avatar{width:28px;height:28px;font-size:10px}
  .sysline{padding-left:38px}
  .sysline .sic{margin-left:-28px}
  .offer,.composer{margin-left:0}
  .itabs{margin-left:0}
  .rev-note{margin-left:0!important}
  .ov-cmd{padding-top:7vh}
  .m-ov{padding:10px}
  .modal{border-radius:16px}
  .oact .right{width:100%;margin-left:0}
  .conn-hero .r{margin-left:0;width:100%}
  .done-act{flex-direction:column;align-items:stretch}
  .proto{display:none}
  .switcher{display:none!important}
  .employee-home-case,.employee-case-list-row,.branch-case-row{
    grid-template-columns:70px minmax(0,1fr)!important;
    gap:8px 10px;align-items:start;padding:12px;
  }
  .employee-home-case > .tid,.employee-case-list-row > .tid,.branch-case-row > .tid{grid-column:1;grid-row:1}
  .employee-home-case > .tt,.employee-case-list-row > .tt,.branch-case-row > .tt{grid-column:2;grid-row:1}
  .employee-home-case > .case-row-priority{grid-column:1;grid-row:2}
  .employee-home-case > .case-row-status{grid-column:2;grid-row:2}
  .employee-case-list-row > .mut2{grid-column:2;grid-row:2}
  .employee-case-list-row > .case-row-priority{grid-column:1;grid-row:3}
  .employee-case-list-row > .case-row-status{grid-column:2;grid-row:3}
  /* The store's list says a floor for the widths where it is a table (W-01,
     employee.js). Here a row is a card, so the floor is off and the heading,
     which names five columns that are not there, goes: it used to stand over
     the cards 620px wide and let the whole list be pushed sideways. */
  .tbl .trow.employee-case-list-row[style*="--floor"]{min-width:0}
  .tbl .trow-h.employee-case-list-h{display:none}
  .branch-case-row > :nth-child(3){grid-column:2;grid-row:2}
  .branch-case-row > :nth-child(4){grid-column:1;grid-row:2}
  .overview-tender-row{
    grid-template-columns:minmax(0,1fr) auto!important;
    padding:10px 12px;align-items:start;
  }
  .overview-tender-row>:nth-child(3),.overview-tender-row>:nth-child(4){display:none}
  .approval-row{
    grid-template-columns:minmax(0,1fr) auto!important;
    padding:10px 12px;align-items:start;
  }
  .approval-row>.tt{grid-column:1/3;grid-row:1}
  .approval-row>.mut{grid-column:1;grid-row:2}
  .approval-row>.mut2{grid-column:2;grid-row:2;text-align:right}
  .approval-row>.approval-actions{grid-column:1/3;grid-row:3;justify-content:flex-start;width:auto}
  .branch-service-row{
    grid-template-columns:minmax(0,1fr) auto!important;
    padding:10px 12px;align-items:start;
  }
  .branch-service-row>.tt{grid-column:1/3;grid-row:1}
  .branch-service-row>.mut{grid-column:1;grid-row:2}
  .branch-service-row>.mut2{grid-column:2;grid-row:2;text-align:right}
  .branch-service-row>.chip{grid-column:1/3;grid-row:3;justify-self:start}
  .sla-summary{gap:3px 8px}
  .sla-mini{width:100%}
}

/* ============ Tags (labels on tickets/tasks) ============ */
.tagrow{display:flex;flex-wrap:wrap;gap:5px;align-items:center}
.ttag{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 9px;border-radius:7px;font-size:11px;font-weight:650;line-height:1;white-space:nowrap;
  background:color-mix(in srgb,var(--tc,#5A6474) 13%,transparent);
  color:var(--tc,#5A6474);
  border:1px solid color-mix(in srgb,var(--tc,#5A6474) 26%,transparent)}
.ttag .tdot{width:7px;height:7px;border-radius:2px;background:var(--tc,#5A6474);flex-shrink:0}
/* A tag wears its own colour as text, and the eight there are were chosen for
   a white card: on the dark one they read 1.8 to 3.3:1 (W-09). Lifted toward
   white the way the brand colour is, each stays its hue and is 7:1 or more. */
html.dark .ttag{color:color-mix(in srgb,var(--tc,#5A6474) 45%,#fff)}
html.dark .ttag .tdot{background:currentColor}
.ttag.rm{padding-right:4px}
.ttag .tx{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:4px;cursor:pointer;opacity:.65}
.ttag .tx:hover{opacity:1;background:color-mix(in srgb,var(--tc,#5A6474) 22%,transparent)}
.ttag .tx svg{width:9px;height:9px}
.tag-add{display:inline-flex;align-items:center;gap:4px;height:22px;padding:0 9px;border-radius:7px;border:1px dashed var(--border);background:none;color:var(--text-3);font:inherit;font-size:11px;font-weight:600;cursor:pointer;transition:border-color .13s,color .13s}
.tag-add:hover{border-color:var(--brand);color:var(--brand)}
.tag-add svg{width:10px;height:10px}
/* The locations in the new-workspace wizard (V-07). On a phone a location is
   two lines, its name over its address, and with the same 8px between every
   field two locations read as four fields of one list. Where they stack (a
   row with its ✕ needs 386px, which the card has from 452px up), a line and
   some air part one location from the next. */
@media (max-width:451px){
  .ob-loc + .ob-loc{margin-top:12px;padding-top:12px;border-top:1px solid var(--border-2)}
}
/* tag option (used in the tag picker + tag manager) */
.tagopt{display:inline-flex;align-items:center;gap:7px;height:30px;padding:0 12px;border-radius:9px;font:inherit;font-size:12px;font-weight:600;cursor:pointer;transition:all .13s;
  background:var(--card);color:var(--tc,#5A6474);border:1px solid color-mix(in srgb,var(--tc,#5A6474) 30%,transparent)}
.tagopt .tdot{width:9px;height:9px;border-radius:3px;background:var(--tc,#5A6474);flex-shrink:0}
.tagopt .tk{width:15px;display:inline-flex}.tagopt .tk svg{width:13px;height:13px}
.tagopt.on{background:color-mix(in srgb,var(--tc,#5A6474) 14%,transparent)}
.tagopt:hover{filter:brightness(.99);border-color:var(--tc,#5A6474)}
.tagmgr-row{display:grid;grid-template-columns:1fr 120px 40px;gap:10px;align-items:center;padding:9px 2px;font-size:12.5px}
.tagmgr-row + .tagmgr-row{border-top:1px solid var(--border-2)}
.swatchpick{display:flex;gap:7px;flex-wrap:wrap}
.swatchpick .sw{width:24px;height:24px;border-radius:7px;cursor:pointer;border:2px solid transparent;position:relative}
.swatchpick .sw.on{border-color:var(--ink);box-shadow:0 0 0 2px var(--card) inset}

/* ============ Activity log (audit timeline) ============ */
.actlog{padding:8px 4px 4px}
.act-item{display:grid;grid-template-columns:24px 1fr;gap:11px;position:relative;padding:0 0 15px}
.act-item::before{content:"";position:absolute;left:11px;top:25px;bottom:-1px;width:1.5px;background:var(--border-2)}
.act-item:last-child{padding-bottom:2px}
.act-item:last-child::before{display:none}
.act-ic{width:24px;height:24px;border-radius:8px;background:#EFF1F5;color:var(--text-2);display:grid;place-items:center;z-index:1}
.act-ic svg{width:12px;height:12px}
.act-ic.g{background:var(--green-bg);color:var(--green)}
.act-ic.b{background:var(--brand-50);color:var(--brand)}
.act-ic.a{background:var(--amber-bg);color:var(--amber)}
.act-ic.r{background:var(--red-bg);color:var(--red)}
.act-b{font-size:12.5px;color:var(--text-2);line-height:1.5;padding-top:3px;min-width:0}
.act-b b{color:var(--ink);font-weight:650}
.act-t{display:block;font-size:11px;color:var(--text-3);margin-top:1px}
html.dark .act-ic{background:#202734}

/* ============ Stats (breakdowns) ============ */
.statgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px}
.donutwrap{display:flex;align-items:center;gap:18px;padding:14px 18px 18px;flex-wrap:wrap}
.donut{position:relative;width:118px;height:118px;border-radius:50%;display:grid;place-items:center;flex-shrink:0}
.donut::before{content:"";position:absolute;inset:15px;border-radius:50%;background:var(--card)}
.donut .dnum{position:relative;font-family:var(--font-display);font-weight:750;font-size:21px;color:var(--ink);line-height:1;text-align:center}
.donut .dsub{position:relative;font-size:10px;color:var(--text-3);margin-top:3px;text-align:center}
.legend{display:flex;flex-direction:column;gap:10px;flex:1;min-width:130px}
.leg{display:flex;align-items:center;gap:9px;font-size:12.5px}
.leg .lg-dot{width:11px;height:11px;border-radius:3px;flex-shrink:0}
.leg .lg-l{color:var(--text-2)}
.leg .lg-n{margin-left:auto;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.leg .lg-s{font-size:11px;color:var(--text-3);margin-left:6px;font-weight:500}
.stat-tile{border:1px solid var(--border);border-radius:13px;background:var(--card);padding:13px 15px}
.stat-tile .st-l{font-size:11.5px;color:var(--text-2);font-weight:600}
.stat-tile .st-v{font-family:var(--font-display);font-weight:750;font-size:22px;color:var(--ink);margin-top:5px;font-variant-numeric:normal}
.stat-tile .st-f{font-size:11px;color:var(--text-3);margin-top:3px}
.bar-fill.cx{background:linear-gradient(90deg,#F3B13C,#DB8E08)}
.bar-fill.pur{background:linear-gradient(90deg,#9A7BE0,#6D3FB8)}
.bar-row .bl.strong{color:var(--ink);font-weight:600}

/* ============ Per-subcontractor isolation (buyer task) ============ */
.subswitch{display:flex;gap:6px;flex-wrap:wrap;padding:0 0 12px}
.subtab{display:inline-flex;align-items:center;gap:8px;padding:6px 12px 6px 7px;border-radius:10px;border:1px solid var(--border);background:var(--card);cursor:pointer;font:inherit;font-size:12.5px;font-weight:600;color:var(--text-2);transition:all .14s}
.subtab .st-av{width:22px;height:22px;border-radius:7px;display:grid;place-items:center;color:#fff;font-size:9px;font-weight:700;flex-shrink:0}
.subtab .st-m{display:flex;flex-direction:column;line-height:1.25;text-align:left}
.subtab .st-bid{font-size:10.5px;color:var(--text-3);font-weight:600}
.subtab.on{border-color:var(--brand);background:var(--brand-50);color:var(--ink)}
.subtab.on .st-bid{color:var(--brand)}
.subtab:hover{border-color:#CBD6E4}
.subtab .st-badge{width:7px;height:7px;border-radius:50%;background:var(--amber-dot);flex-shrink:0}
.privhead{display:flex;align-items:center;gap:9px;font-size:11.5px;color:var(--text-3);background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:9px 12px;margin-bottom:12px;line-height:1.45}
.privhead svg{width:15px;height:15px;flex-shrink:0;color:var(--text-3)}
.privhead b{color:var(--text-2);font-weight:650}

/* ============ Helpdesk parity (collision · followers · bulk · merge) ============ */
.viewing{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:650;color:var(--amber);background:var(--amber-bg);border:1px solid var(--amber-br);border-radius:999px;padding:3px 10px 3px 3px}
.viewing .vw-av{width:18px;height:18px;border-radius:50%;background:var(--amber-dot);color:#fff;display:grid;place-items:center;font-size:8px;font-weight:700}
.viewing svg{width:12px;height:12px}
.follstack{display:flex;align-items:center;padding-left:6px}
.follstack .avatar{margin-left:-7px;border:2px solid var(--card);width:27px;height:27px;font-size:9.5px}
.follstack .fmore{margin-left:-7px;width:27px;height:27px;border-radius:50%;border:2px solid var(--card);background:#EDF0F4;color:var(--text-2);display:grid;place-items:center;font-size:10px;font-weight:700}
html.dark .follstack .fmore{background:#202734}
.bulkbar{display:flex;align-items:center;gap:11px;padding:9px 14px;background:var(--ink);color:#fff;border-radius:11px;margin-bottom:10px;animation:rise .3s both}
.bulkbar .bk-n{font-weight:700}
.bulkbar .bk-act{display:flex;gap:7px;margin-left:auto;flex-wrap:wrap}
.bulkbar .bkbtn{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:8px;font:inherit;font-size:12px;font-weight:600;cursor:pointer;background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.18)}
.bulkbar .bkbtn:hover{background:rgba(255,255,255,.2)}
.bulkbar .bkbtn svg{width:12px;height:12px}
html.dark .bulkbar{background:#202734;border:1px solid var(--border)}
.rowcheck{width:16px;height:16px;accent-color:var(--brand);cursor:pointer;flex-shrink:0}
.linkline{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-2);padding:7px 11px;border:1px solid var(--border);border-radius:9px;background:var(--bg);margin-bottom:8px}
.linkline svg{width:13px;height:13px;color:var(--text-3);flex-shrink:0}
.linkline b{color:var(--ink);font-weight:650}
.linkline .ll-x{margin-left:auto;color:var(--text-3);cursor:pointer;display:inline-flex}
.linkline .ll-x svg{width:12px;height:12px}
/* clickable div-rows (bulk select) */
.trow.pick{cursor:pointer}
.trow.pick:hover{background:#F8F9FB}
html.dark .trow.pick:hover{background:#1B212C}
.trow.pick.on{background:var(--brand-50)}
html.dark .trow.pick.on{background:rgba(91,150,224,.10)}
.tidcell{display:flex;align-items:center;gap:9px}
.tidcell .rowcheck{margin:0}
/* The tick column. A larger hit area than the box itself, because this is the
   one control on a row where the surrounding click does something else. */
.trow > span > input[type=checkbox],
.trow-h > span > input[type=checkbox]{
  width:15px;height:15px;margin:0;cursor:pointer;accent-color:var(--brand);vertical-align:middle;
}
.trow > span:has(> input[type=checkbox]),
.trow-h > span:has(> input[type=checkbox]){display:flex;align-items:center;padding:2px 0}
.savedrow{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:0 0 2px}
.pill.saved i{width:7px;height:7px;border-radius:2px;margin-right:5px;display:inline-block}
.pill.ghostpill{background:none;border-style:dashed;color:var(--text-3);display:inline-flex;align-items:center;gap:5px}
.pill.ghostpill:hover{color:var(--brand);border-color:var(--brand)}
.pill svg{width:13px;height:13px;flex-shrink:0;vertical-align:-2px}
/* status control on the ticket (this is where status is changed) */
.statuspick{position:relative;display:inline-flex;align-items:center;gap:6px;height:27px;padding-left:11px;border-radius:999px;border:1px solid var(--border);background:var(--card);color:var(--text-2)}
.statuspick i.d{width:7px;height:7px;border-radius:50%;background:currentColor;flex-shrink:0}
.statuspick select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:none;border:none;font:inherit;font-size:12px;font-weight:650;color:inherit;padding:0 25px 0 5px;height:27px;cursor:pointer}
.statuspick select:focus{outline:none}
.statuspick::after{content:"";position:absolute;right:11px;top:50%;transform:translateY(-62%) rotate(45deg);width:5px;height:5px;border-right:1.7px solid currentColor;border-bottom:1.7px solid currentColor;pointer-events:none;opacity:.65}
.statuspick:hover{filter:brightness(.985)}
.statuspick.s-progress,.statuspick.s-planned{color:var(--brand);background:var(--brand-50);border-color:var(--brand-100)}
.statuspick.s-open,.statuspick.s-approval{color:var(--amber);background:var(--amber-bg);border-color:var(--amber-br)}
.statuspick.s-waiting,.statuspick.s-onhold{color:var(--text-2);background:#F2F3F6;border-color:var(--border)}
.statuspick.s-solved{color:var(--green);background:var(--green-bg);border-color:var(--green-br)}
html.dark .statuspick.s-waiting,html.dark .statuspick.s-onhold{background:#202734}

/* ============================================================
   AUDIT ROUND 2026-07-23 · shared foundation
   ============================================================ */

/* Skip link (a11y) */
.skiplink{position:fixed;top:-48px;left:14px;z-index:200;background:var(--ink);color:var(--card);font-size:12.5px;font-weight:700;padding:9px 15px;border-radius:0 0 10px 10px;transition:top .15s ease;text-decoration:none}
.skiplink:focus-visible{top:0;outline:2px solid var(--brand);outline-offset:2px}

/* Reduced motion: sluk indløbs- og pulsanimationer */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}
}

/* Touch targets på grove pegeredskaber */
@media (pointer: coarse){
  .btn.sm,.cbtn,.fsel select,.ftext input,.tab,.seg2 button,.attach,.send,.toast.ask button{min-height:44px}
  .nav-item{min-height:44px}
  /* The primary button and the icon buttons were 38px, under the 44px a
     thumb needs; the poster's Send measured 42. */
  .btn,.icon-btn{min-height:44px}
  .icon-btn{min-width:44px}
}
/* ⚠️ iOS ZOOMS THE PAGE ON EVERY FOCUS BELOW 16PX, and every field in the
   product was 13.5 or 14. The layout jumped on each tap. Sixteen on anything
   touch-driven or phone-wide; maximum-scale is deliberately NOT set, so pinch
   zoom stays for the people who need it. */
@media (pointer: coarse), (max-width: 640px){
  .f-input,select.f-input,textarea.f-input,.composer input,.composer textarea,.auth-field .f-input,.ftext input{font-size:16px;min-height:44px}
}
/* A modal is never taller than the screen that is left, and on a phone it is
   a sheet from the bottom whose buttons stay in reach above the keyboard. */
.modal{max-height:calc(100dvh - 24px)}
@media (max-width:640px){
  .m-ov{align-items:end;justify-items:stretch;padding:0}
  .modal{width:100%;max-width:none;border-radius:16px 16px 0 0;max-height:calc(100dvh - 12px)}
  .m-f{position:sticky;bottom:0;background:var(--card);padding-bottom:max(18px,env(safe-area-inset-bottom))}
  /* And a toast from the action before is not on those buttons: both are at
     the bottom of a phone, so "Arbejdet er i gang." covered "Annullér" in the
     sheet opened next. While a sheet is open the toasts are at the top. */
  body:has(.m-ov) .toasts{bottom:auto;top:max(12px,env(safe-area-inset-top))}
}

/* A refusal inside a dialog: the `class="err"` line a save handler fills. No
   rule matched it, so it was ordinary body text (test round F-034). The exact
   attribute, so .f-input.err, .upl.err and the others keep their own meaning.
   FogiDeskChrome moves the sentence under the field it is about when it can,
   and this line then stands down. */
[class="err"]{color:var(--red);font-size:12.5px;font-weight:650;line-height:1.4;margin-top:10px}
[class="err"][data-at-field]{display:none}
/* Inline feltvalidering */
.f-err{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:650;color:var(--red);margin-top:5px;line-height:1.35}
.f-err svg{width:12px;height:12px;flex-shrink:0}
/* display:flex above beats the browser's own [hidden] rule, so a message the
   form had hidden again stayed on screen under a field already put right. */
.f-err[hidden]{display:none}
.f-input.err{border-color:var(--red) !important;box-shadow:0 0 0 3px rgba(199,74,58,.12)}
html.dark .f-input.err{box-shadow:0 0 0 3px rgba(240,117,102,.14)}

/* Truthful labelling: simuleret vs. roadmap */
.simtag{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:750;letter-spacing:.05em;text-transform:uppercase;color:var(--amber);background:var(--amber-bg);border:1px solid var(--amber-br);border-radius:6px;padding:2px 7px;vertical-align:2px}
.roadtag{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:750;letter-spacing:.05em;text-transform:uppercase;color:var(--text-3);background:none;border:1px dashed var(--border);border-radius:6px;padding:2px 7px;vertical-align:2px}
.roadcard{opacity:.72}
.roadcard:hover{opacity:1}

/* Vedhæftnings-chips (foto i indmeldingsflows) */
.attach-chips{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.attach-chip{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:650;color:var(--text);background:var(--brand-50);border:1px solid var(--brand-100);border-radius:9px;padding:6px 8px 6px 10px;max-width:240px}
.attach-chip svg{width:13px;height:13px;color:var(--brand);flex-shrink:0}
.attach-chip b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:650}
.attach-chip .rm{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border:none;background:none;color:var(--text-3);cursor:pointer;border-radius:5px;font-size:13px;line-height:1}
.attach-chip .rm:hover{background:rgba(0,0,0,.07);color:var(--red)}

/* Not-found side */
.nf-wrap{max-width:520px;margin:60px auto 0;text-align:center}
.nf-code{font-family:var(--font-display);font-size:46px;font-weight:800;color:var(--text-3);letter-spacing:.02em}
.nf-wrap h1{margin:6px 0 8px}
.nf-wrap p{font-size:13.5px;color:var(--text-2);line-height:1.6;margin:0 0 18px}

/* Økonomi-ordforråd · legend + stacked budget-bar */
.fin-legend{display:flex;gap:14px;flex-wrap:wrap;font-size:11.5px;color:var(--text-2);align-items:center}
.fin-legend i{display:inline-block;width:9px;height:9px;border-radius:3px;margin-right:5px;vertical-align:-1px}
.bgt-bar{position:relative;height:14px;border-radius:7px;background:var(--border-2);overflow:hidden;display:flex}
.bgt-bar .seg{height:100%}
.bgt-bar .seg.actual{background:var(--brand)}
.bgt-bar .seg.commit{background:var(--brand);opacity:.45}
.bgt-bar .seg.forecast{background:repeating-linear-gradient(-45deg,var(--amber-dot) 0 4px,transparent 4px 8px);opacity:.75}
.bgt-bar.over{box-shadow:0 0 0 1.5px var(--red)}
.bgt-row{display:grid;grid-template-columns:minmax(120px,1.2fr) 2fr minmax(110px,max-content);gap:12px;align-items:center;padding:9px 18px;border-top:1px solid var(--border-2);font-size:12.5px}
.bgt-row:first-child{border-top:none}
/* ⚠️ A BUDGET ROW'S LABEL IS READ WHOLE (Y-09). It was one line cut with
   three dots, in a column that is 133px on a desk and 92px on a phone:
   "Døre, porte og vind…", and a store's name the same way. The full name
   was in the tooltip, and nobody can hover on a phone. It wraps, like the
   chart labels (X-09), and only a single word longer than the column is
   broken inside. The row grows by a line; the bar and the amount stay in
   the middle of it. */
.bgt-row .bl{font-weight:650;color:var(--text);overflow-wrap:anywhere}
.bgt-row .bl span{display:block;font-weight:500;font-size:11px;color:var(--text-3)}
.bgt-row .bv{text-align:right;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.bgt-row .bv small{display:block;font-weight:550;font-size:10.5px;color:var(--text-3)}
/* ⚠️ THE AMOUNT IN A BUDGET ROW IS ONE LINE, AND ITS COLUMN GROWS TO HOLD IT
   (W-04). The column was 110px (92 under 820px) whatever stood in it, and
   since <body> breaks a word that has no room, "DKK 56,451.50" stood as
   "DKK 56,451.5" over "0" and a figure from a million up was cut inside its
   digits. The amount never wraps; the small line under it still does, and it
   is told not to count toward the column's width (width:0 with min-width:100%
   takes the column it is given and asks for none), so only the amount can
   widen it. */
.bgt-row .bv{white-space:nowrap}
.bgt-row .bv small{white-space:normal;width:0;min-width:100%}
.bgt-row.over .bv{color:var(--red)}

/* Budget-KPI'er med præcise begreber */
.finkpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.finkpi .fk{background:var(--card);border:1px solid var(--border);border-radius:13px;padding:12px 14px}
.finkpi .fk .l{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-3);display:flex;align-items:center;gap:6px}
.finkpi .fk .l i{width:8px;height:8px;border-radius:3px;display:inline-block;flex-shrink:0}
.finkpi .fk .v{font-family:var(--font-display);font-size:19px;font-weight:750;color:var(--ink);margin-top:5px;font-variant-numeric:normal}
.finkpi .fk .v small{font-size:11.5px;font-weight:600;color:var(--text-3)}
/* The same for the budget's tiles (W-04): "kr." fell onto a line of its own
   under "261.084,50". .54 here, because the unit is set small. */
.finkpi .fk{container-type:inline-size}
.finkpi .fk .v{white-space:nowrap;font-size:min(19px,calc(100cqi / (var(--len,8) * .54)))}
.finkpi .fk .f{font-size:11px;color:var(--text-3);margin-top:3px;line-height:1.4}
.finkpi .fk.neg .v{color:var(--red)}

/* Definition-tooltips på metrikker */
.defhint{position:relative;display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;border:1px solid var(--border);color:var(--text-3);font-size:9.5px;font-weight:800;cursor:help;vertical-align:1px;margin-left:5px}
.defhint:hover::after,.defhint:focus-visible::after{content:attr(data-def);position:absolute;bottom:calc(100% + 7px);left:50%;transform:translateX(-50%);width:230px;background:var(--ink);color:var(--card);font-size:11px;font-weight:550;line-height:1.5;padding:9px 11px;border-radius:9px;z-index:60;box-shadow:var(--shadow-lg);text-transform:none;letter-spacing:0;white-space:normal;text-align:left}
html.dark .defhint:hover::after,html.dark .defhint:focus-visible::after{background:#E8EDF4;color:#1A212B}

/* Kilde & friskhed-linje under rapporter */
.srcline{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--text-3);padding:10px 18px;border-top:1px dashed var(--border)}
.srcline svg{width:12px;height:12px;flex-shrink:0}

/* Fakturadetalje-modal */
.inv-lines{border:1px solid var(--border);border-radius:11px;overflow:hidden;margin:10px 0 4px}
.inv-line{display:grid;grid-template-columns:1fr 90px 110px;gap:10px;padding:9px 13px;font-size:12.5px;border-top:1px solid var(--border-2);align-items:center}
.inv-line:first-child{border-top:none}
.inv-line .t{font-weight:600;color:var(--text)}
.inv-line .t span{display:block;font-weight:500;font-size:11px;color:var(--text-3)}
.inv-line .a{text-align:right;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.inv-line.sum{background:var(--bg);font-weight:750}

/* Historik/audit-blok i modaler */
.audit-line{display:flex;gap:9px;font-size:12px;color:var(--text-2);padding:7px 0;border-top:1px dashed var(--border-2);line-height:1.5}
.audit-line:first-child{border-top:none}
.audit-line .when{flex-shrink:0;font-weight:650;color:var(--text-3);width:88px}

/* Kategori-manager (buyer) */
.catrow{display:grid;grid-template-columns:minmax(140px,1.4fr) 1fr 120px 120px;gap:12px;align-items:center;padding:10px 18px;border-top:1px solid var(--border-2);font-size:12.5px}
.catrow:first-child{border-top:none}
.catrow.archived{opacity:.55}
.catrow .cn{display:flex;align-items:center;gap:9px;font-weight:650;color:var(--text)}
.catrow .cn svg{width:15px;height:15px;color:var(--text-3);flex-shrink:0}
.catrow .cn .cid{font-size:10px;font-weight:600;color:var(--text-3);background:var(--bg);border:1px solid var(--border-2);padding:1px 6px;border-radius:5px}
.catrow .acts{display:flex;gap:6px;justify-content:flex-end}

/* Kontrast: amber-tekst på hvid gjort mørkere hvor den står alene */
.mut-amber{color:#8A5202;font-weight:650}
html.dark .mut-amber{color:var(--amber)}

/* Genbrugelig tom/ikke-fundet tilstand i lister */
.empty-nf{padding:26px 18px;text-align:center;font-size:12.5px;color:var(--text-3);line-height:1.6}

/* Kontering låst efter godkendelse (audit) */
.cx-seg.locked{opacity:.75;position:relative}
.cx-seg.locked .cx-opt{cursor:not-allowed}
.cx-seg.locked .cx-opt.on{cursor:pointer} /* den aktive kan klikkes for ompostering-med-begrundelse */
.cx-seg.locked .cx-opt:not(.on){cursor:pointer} /* klik åbner ompostering-dialogen */

/* Audit P0-05b: tabeller med inline-kolonner må ALDRIG klippes væk på smalle skærme ·
   de scroller i deres egen container, så alt indhold kan nås */
@media (max-width:820px){
  .tbl{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl .trow[style*="grid-template-columns"],
  .tbl .trow-h[style*="grid-template-columns"]{min-width:620px}
  .tbl .catrow{min-width:620px}
  /* Head office's case list and the location register are not tables at
     this width: see the rules for .hqlist and .brow below (V-17). */
  /* The audit trail has 490px of fixed columns since its last one grew to
     hold "Jeres eget hold" (F-031): at 620px the sentence, which is the row,
     was 58px wide. 730px leaves it 168, which is also what a 390px phone
     shows beside the time before anything is scrolled. */
  .tbl .trow.aurow[style*="grid-template-columns"],
  .tbl .trow-h.aurow[style*="grid-template-columns"]{min-width:730px}
  /* ⚠️ THE SAME RULE FOR ROWS THAT SIT IN A PANEL RATHER THAN A .tbl. The
     groups under the location register, the SLA targets and "who is on what"
     are inline-column rows inside a .panel, and nothing let them scroll: at
     375px they pushed the whole page 134px and 236px sideways (walk, 28 Sep).
     Their own wrapper scrolls instead, never the panel, whose menus and
     hints must not be cut off. */
  .panel div:has(> .trow[style*="grid-template-columns"]),
  .panel div:has(> .trow-h[style*="grid-template-columns"]){overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* Where the rows are the panel's own children (support access, retention
     holds) there is no wrapper, and the panel is the only box that can. */
  .panel:has(> .trow[style*="grid-template-columns"]),
  .panel:has(> .trow-h[style*="grid-template-columns"]){overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* 760, not the .tbl's 620: these rows carry more fixed columns (the SLA
     targets alone are 530px of them), and at 620 their one free column, the
     one that says what the row is, came out 6px wide. */
  .panel .trow[style*="grid-template-columns"],
  .panel .trow-h[style*="grid-template-columns"]{min-width:760px}
  .budget-branch-table{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .budget-branch-table .trow[style*="grid-template-columns"],
  .budget-branch-table .trow-h[style*="grid-template-columns"]{min-width:620px}
  .finkpi{grid-template-columns:repeat(2,1fr)}
  .bgt-row{grid-template-columns:minmax(90px,1fr) 1.4fr minmax(92px,max-content);padding:9px 12px}
}
/* ⚠️ A WINDOW OF 1024px HAS LESS ROOM FOR A TABLE THAN ONE OF 768px (W-01).
   Above 920px the menu is back beside the page and takes 242px, so between
   921 and 1180 a table is 620 to 880px wide, and the floors above stop at
   820. The two widest registers fell through the gap: at 1024 the location
   register's name column was 17px and head office's titles 60px, one or two
   letters to a line. They kept a floor and scrolled in their own box up to
   1180 at first, which cut the status off at the edge of the box (V-17):
   they are laid out for the width now, with the people and the rollout below.
   And 620 is not every table's floor. One whose fixed columns come to about
   600px (the invoices, the desk's customers, the supplier register) had 14
   and 10px left for who it is to and which case, at 641px and again at 921.
   Such a table says its own floor beside its columns, where the widths are
   known: --floor on the row. 720 where it is used, which is what the table
   has at 1024, so nothing that fits there starts to scroll. */
@media (max-width:1180px){
  .tbl{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl .trow[style*="--floor"],.tbl .trow-h[style*="--floor"]{min-width:var(--floor)}
}
/* The same gap for the audit trail (its sentence was 60px at 921) and for a
   row in a panel that says its floor (the desk's service targets: 9px for
   "Bruges når"). Only between the two widths: under 820 the rules above
   already hold them. */
@media (min-width:821px) and (max-width:1180px){
  .tbl .trow.aurow[style*="grid-template-columns"],
  .tbl .trow-h.aurow[style*="grid-template-columns"]{min-width:720px}
  .panel div:has(> .trow[style*="--floor"]){overflow-x:auto;-webkit-overflow-scrolling:touch}
  .panel .trow[style*="--floor"],.panel .trow-h[style*="--floor"]{min-width:var(--floor)}
}
/* ⚠️ A BOX THAT SCROLLS SIDEWAYS SAYS SO (X-07, X-14). The rules above keep a
   wide table whole by letting it scroll in its own box, and nothing on the
   screen said that it did: Insight ended at "Åbne nu" and the routing matrix
   at "Var", cut by the card's edge as if that were all of it.
   A list is laid out for the width wherever it can be (cards, two lines,
   below). A real matrix cannot, so its box is marked `scrollx`, and so is
   any other box that is left to scroll; a .tbl that the floors above still
   let scroll wears the same cue.
   The cue is a soft shadow down the edge that has more behind it, and it
   needs no script: the two shadows are painted on the box and stay where
   they are (scroll), and over each lies a patch of the card's own colour
   that travels with the content (local). So a shadow shows only while its
   side has more to see, goes at the end of the scroll, and a box that fits
   shows neither. --ink is the dark token on a light card and the light one
   on a dark card, so the edge reads in both themes. The patch is opaque for
   16px and the shadow is 14px wide, so a box that does not scroll has no
   line down its edge; and the shadow stops 16px short of the top and of the
   foot, clear of a card's round corners, where a covered shadow still tints
   the few pixels that draw the curve.
   Only where color-mix exists: a browser without it would throw the whole
   background away, the card's own colour with it.
   ⚠️ AND A BROWSER WITHOUT IT HAD NO CUE AT ALL (Safari before 16.2, Chrome
   before 111: the older phones and tablets a store still has). It gets the
   same cue written without color-mix, in the block after this one: the
   shadow is the theme's --ink at the same 26%, spelled out per theme
   (--edge-ink), and the patch is the card's colour for 16px with no fade,
   because those browsers fade to `transparent` through grey and would
   leave a smudge down the edge of every box that fits. Asked for only where
   `local` is understood, for the reason above. */
.scrollx{overflow-x:auto;-webkit-overflow-scrolling:touch}
@supports (color:color-mix(in srgb,red,blue)){
  .scrollx,.tbl{--edge-cue:
    linear-gradient(to right,var(--card) 50%,transparent) 0 0/32px 100% no-repeat local,
    linear-gradient(to left,var(--card) 50%,transparent) 100% 0/32px 100% no-repeat local,
    linear-gradient(to right,color-mix(in srgb,var(--ink) 26%,transparent),transparent) 0 50%/14px calc(100% - 32px) no-repeat scroll,
    linear-gradient(to left,color-mix(in srgb,var(--ink) 26%,transparent),transparent) 100% 50%/14px calc(100% - 32px) no-repeat scroll}
  .scrollx{background:var(--edge-cue)}
  @media (max-width:1180px){
    .tbl{background:var(--edge-cue),var(--card)}
  }
}
@supports (background-attachment:local) and (not (color:color-mix(in srgb,red,blue))){
  .scrollx,.tbl{--edge-ink:rgba(15,21,34,.26);--edge-cue:
    linear-gradient(var(--card),var(--card)) 0 0/16px 100% no-repeat local,
    linear-gradient(var(--card),var(--card)) 100% 0/16px 100% no-repeat local,
    linear-gradient(to right,var(--edge-ink),transparent) 0 50%/14px calc(100% - 32px) no-repeat scroll,
    linear-gradient(to left,var(--edge-ink),transparent) 100% 50%/14px calc(100% - 32px) no-repeat scroll}
  html.dark .scrollx,html.dark .tbl{--edge-ink:rgba(241,245,250,.26)}
  .scrollx{background:var(--edge-cue)}
  @media (max-width:1180px){
    .tbl{background:var(--edge-cue),var(--card)}
  }
}
/* ⚠️ AND ON A PHONE THOSE ROWS WERE CUT AT THE CARD'S EDGE, WITH NO SIGN OF
   MORE (the last walk, V-08). A row in a panel keeps its 760px floor and
   scrolls in its own box, which a tablet can live with. At 390px the desk's
   service targets ended at "FØRSTE SV", "who is on what" showed the customer
   and neither its level nor its figure, and the plans lost their interval.
   A panel's rows marked `cards` are cards under 640px, by the same marks as
   a .tbl's (below): the cell marked data-col="ref" and the one marked
   "status" share the first line, the rest stack under it, and a cell that
   was told apart by its column says its heading in front (data-k). */
@media (max-width:640px){
  .panel .cards .trow-h{display:none}
  .panel .cards .trow[style*="grid-template-columns"]{
    grid-template-columns:minmax(0,1fr) auto!important;min-width:0;gap:4px 10px;padding:12px 18px;align-items:center
  }
  .panel .cards .trow > *{grid-column:1/-1;order:1}
  .panel .cards .trow > [data-col="ref"]{grid-column:1;order:-2}
  .panel .cards .trow > [data-col="status"]{grid-column:2;order:-1;justify-self:end}
  .panel .cards .trow > [data-k]{font-size:12px}
  .panel .cards .trow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
  /* A figure with a line under it ("8 t" over "cirka 22 t") stays beside its
     heading, with the line after it. */
  .panel .cards .trow > .tt[data-k] b{display:inline;margin-right:6px}
  /* A firm on a customer's list with two chips, "Inviteret · udløber …" and
     "På pause", left its name some 25px at 390 and spelt it a few letters a
     line (w14b check): two chips go under the name instead. */
  #cuFirms .cards .trow > [data-col="status"]:has(> .chip + .chip){grid-column:1/-1;justify-self:start}
}
/* ⚠️ AND BETWEEN A PHONE AND 820px THE SAME ROWS STILL SCROLLED IN THEIR BOX
   (the walk of the merged build, X-03). The 760px floor above is for a
   panel's rows in general. The desk's rows marked `cards` are laid out to
   fit a 610px box, so from 641px they are the table with every column in
   sight ("Ur", "Type" and "Har adgang til" stood past the edge with no sign
   of more), and under it the cards above. */
@media (min-width:641px) and (max-width:820px){
  .panel .cards .trow[style*="grid-template-columns"],
  .panel .cards .trow-h[style*="grid-template-columns"]{min-width:0}
}
@media (max-width:480px){
  .finkpi{grid-template-columns:1fr 1fr}
  .stepper{
    display:grid;grid-template-columns:1fr;gap:8px;overflow:visible;
    padding:12px 14px!important;
  }
  .step{
    min-width:0;display:grid;grid-template-columns:24px minmax(0,1fr);
    gap:9px;text-align:left;align-items:start;
  }
  .step::before{
    top:-9px;bottom:auto;left:11px;right:auto;width:2px;height:9px;
  }
  .step>i{margin:0;width:22px;height:22px;grid-column:1;grid-row:1}
  .step>span{grid-column:2;grid-row:1;margin:0;font-size:inherit}
  .step>span>b{margin:1px 0 0;font-size:11px;line-height:1.25}
  .step>span>small{margin-top:2px;font-size:9.5px;line-height:1.35}
}

/* --------------------------------------------------------------------------
   .callout · 25 jul 2026
   Klassen blev brugt 18 steder i kundeportalen og havde ingen regel overhovedet:
   gennemsigtig baggrund, ingen ramme, ingen luft, og <b> løb direkte ind i
   <span>. Fundet under budgetarbejdet, men det ramte alle eksisterende skærme.
   Formsproget følger .op-callout i operatørkonsollen; farverne kommer fra
   design-tokens, så mørk tilstand følger med af sig selv.
   -------------------------------------------------------------------------- */
.callout{
  display:block;
  padding:11px 12px;
  margin-top:10px;
  border:1px solid var(--border-2);
  border-radius:9px 9px 4px 9px;
  background:var(--bg);
  color:var(--text-2);
  font-size:12px;
  line-height:1.55;
  /* Det, der står her, er ofte skrevet af et menneske: en besked til
     håndværkeren, en note ved et bud. Et indsat link på 400 tegn har ingen
     steder at knække, så det løb ud af boksen og gjorde hele siden flere
     tusind pixel bred. `anywhere` tæller også med i boksens mindste bredde,
     så kolonnen omkring den ikke strækkes. */
  overflow-wrap:anywhere;
}
/* Kun overskriften er blok. Et <b> inde i brødteksten skal blive inline,
   ellers brækker "70.000 DKK" over to linjer. */
.callout > b:first-child{
  display:block;
  margin-bottom:3px;
  color:var(--text);
  font-weight:600;
}
.callout > span{ display:block }
.callout > span b{ color:var(--text); font-weight:600 }
.callout + .callout{ margin-top:8px }

.callout.warn{
  border-color:var(--amber-br);
  background:var(--amber-bg);
  color:var(--amber);
}
.callout.warn > b:first-child{ color:var(--amber) }

.callout.danger{
  border-color:var(--red-br);
  background:var(--red-bg);
  color:var(--red);
}
.callout.danger > b:first-child{ color:var(--red) }

/* ---------------------------------------------------------------------------
   Fælles organisationslag (fogidesk-org.js) · 25 jul 2026
   Grupperækkerne lånte .bgt-row, som er bygget til budgetsidens tre kolonner
   med white-space:nowrap. I en smallere modal klippede den undertekster midt i
   et ord ("ejer budgetlinj"). Egen række, der må ombryde.
   --------------------------------------------------------------------------- */
.org-row{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;
  padding:10px 0;border-top:1px solid var(--border-2);font-size:12.5px}
.org-row:first-of-type{border-top:none}
.org-row .ol{font-weight:650;color:var(--text);min-width:0}
.org-row .ol span{display:block;font-weight:500;font-size:11px;color:var(--text-3);
  line-height:1.5;white-space:normal}
.org-row .oa{display:flex;gap:6px;flex-shrink:0}
.org-empty{padding:18px 0;text-align:center;color:var(--text-3);font-size:13px}
@media (max-width:560px){
  .org-row{flex-direction:column;gap:8px}
  .org-row .oa{width:100%}
  .org-row .oa .btn{flex:1}
}

/* ---------------------------------------------------------------------------
   Budget · redigering dér hvor tallet står (fogidesk-budget.js) · 26 jul 2026
   Ejeren bad tre gange om en LETTERE måde at rette en budgetlinje. Den lette
   måde er ikke en dialog · det er et tal, man kan klikke på.
   --------------------------------------------------------------------------- */
.amt-edit{background:none;border:none;padding:0 2px;margin:0;font:inherit;color:var(--brand);
  cursor:pointer;border-bottom:1px dashed var(--brand);border-radius:0}
.amt-edit:hover{background:var(--brand-bg,rgba(14,74,140,.07))}
.amt-edit:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Beløbskolonnen er 110px, og et åbent felt med modpost er bredere. Rækken
   giver plads MENS den redigeres i stedet for at lade feltet flyde ud over
   panelets kant. */
.bgt-row:has(.amt-inline){grid-template-columns:minmax(100px,1fr) 1.5fr 200px}
.amt-inline{display:flex;flex-direction:column;gap:4px;align-items:stretch;width:100%}
.amt-inline .amt-input{width:100%;text-align:right;font-variant-numeric:tabular-nums;
  font-size:13px;padding:5px 8px;border:1px solid var(--brand);border-radius:7px;
  background:var(--card);color:var(--text)}
.amt-inline .amt-counter{width:100%;font-size:10.5px;padding:3px 5px;
  border:1px solid var(--border-2);border-radius:6px;background:var(--card);color:var(--text-3)}
.lnk-row{background:none;border:none;padding:0;margin:0;font:inherit;color:var(--text);
  cursor:pointer;text-align:left;border-bottom:1px dashed var(--border-2)}
.lnk-row:hover{color:var(--brand);border-bottom-color:var(--brand)}

/* Undertekster i budgetrækker må ombryde. .bl står med nowrap for at holde
   navnet på én linje, men underteksten arvede den og blev klippet midt i et
   ord ("fordelt pr. restaura"). (Since Y-09 the name wraps too; this still
   gives the line under it its own line height.) */
.bgt-row .bl span{white-space:normal;line-height:1.45}
/* A firm's note to its answer on a tender (V-25): under the row, at the
   row's whole width, and four lines of it until somebody asks for the rest. */
.bgt-row .bid-note{grid-column:1/-1;margin-top:-4px;font-size:11.5px;line-height:1.5;color:var(--text-3);overflow-wrap:anywhere}
.bgt-row .bid-note > span{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;overflow:hidden}
.bgt-row .bid-note.open > span{display:block}
.bgt-row .bid-note button{display:block;margin-top:3px;padding:0;border:none;background:none;font:inherit;font-weight:650;color:var(--brand);cursor:pointer}
.bgt-row .bid-note button[hidden]{display:none}
/* ⚠️ THE FIRM'S NAME IN ITS ANSWER, ON A PHONE (Z-02). The row's three
   columns (firm, amount, state) stood in its own style attribute, and since
   a label may break inside a word (Y-09) the firm got what the other two
   left over: 17px at 390 when the state is the chip "Afventer en
   beslutning", so "Test AI VVS" stood as Te/st/AI/V/V/S down 113px, right
   above the approver's two buttons. On a phone the name has the row's first
   line to itself, and the amount and the state share the line under it.
   From 641px the three columns are as they were. */
.bgt-row.bid{grid-template-columns:1.4fr 130px 1fr}
@media (max-width:640px){
  .bgt-row.bid{grid-template-columns:auto 1fr;row-gap:5px}
  .bgt-row.bid .bl{grid-column:1/-1}
  .bgt-row.bid .bv{text-align:left}
}
/* In the amount's place, what is not an amount (M-02, amountCell in
   buyer.js): a firm that is not bidding, a price this reader is not shown,
   no answer yet. The quiet tone and an ordinary weight, so none of them is
   read as a figure. The mark for "no price" is drawn, not typed: a dash is
   not a word, and the state beside it says what it is. */
.bgt-row.bid .bv.quiet{font-weight:500;color:var(--text-3)}
.bgt-row.bid .bv.quiet svg{width:13px;height:13px;margin-right:5px;vertical-align:-2px}
.bgt-row.bid .bv.mark::before{content:"";display:inline-block;width:10px;height:2px;border-radius:1px;background:currentColor;vertical-align:middle}

/* ---------- your account ----------
   The sessions list inside the account panel. `.pill` already exists as a
   filter chip; here it is a static marker on the row that is this browser, so
   it takes .pill.here rather than a second class that looks like a chip and
   is not clickable. */
.acct-session{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:9px 0;border-bottom:1px solid var(--line);
}
.acct-session:last-child{border-bottom:0}
.acct-session .pill{cursor:default;margin-left:6px}
.acct-session .pill:hover{border-color:var(--line);color:var(--text-3)}

/* ============ "you are running yesterday's code" ============
   Shown when the server's build no longer matches the one this page loaded.
   Deliberately a bar the person dismisses by using it, not a toast that
   disappears: the whole failure it addresses is somebody not knowing there is
   anything to know. */
.build-bar{
  position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:500;
  display:flex;align-items:center;gap:14px;
  background:var(--ink);color:#fff;
  padding:11px 12px 11px 18px;border-radius:12px;
  box-shadow:var(--shadow-lg);
  font-size:13px;font-weight:500;
  max-width:min(560px,calc(100vw - 32px));
}
.build-bar button{
  background:#fff;color:var(--ink);
  border-radius:8px;padding:7px 14px;
  font-size:12.5px;font-weight:650;white-space:nowrap;
}
.build-bar button:hover{background:#EEF1F5}

/* ============ a file in the conversation ============
   The thread used to say "somebody attached a file" and leave you to find it
   in a card on the other side of the screen. A photograph of a leak is the
   message, not a footnote to it.

   ⚠️ EVERY CLASS HERE IS PREFIXED `fl-`, AND THAT IS NOT STYLE PEDANTRY. The
   first version used .photo, .cap and .ph — all three already meant something
   else in this stylesheet. `.photo span` is a caption overlaid on a photo
   tile, `position:absolute`, so the file's own caption was thrown on top of
   its thumbnail. Nothing errored; it just looked broken. A shared stylesheet
   has one namespace and a generic name in it is a name somebody already
   took. */
.fileline{
  display:flex;align-items:center;gap:11px;
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);
  padding:10px 12px;margin:2px 0 2px 52px;font-size:12.5px;
  /* ⚠️ WIDTH, NOT align-self:stretch. `.thread` is a column flex container so
     stretch is what should size this, and it does not — the card came out at
     its own content width. Measured both in the browser before choosing. 52px
     is the avatar gutter, so a file lines up with the conversation. */
  width:calc(100% - 52px);
}
.fileline .fl-icon{
  width:30px;height:30px;border-radius:9px;background:#F2F3F6;color:var(--text-2);
  display:grid;place-items:center;flex-shrink:0;
}
.fileline .fl-icon svg{width:14px;height:14px}
.fileline .fl-meta{flex:1;min-width:0}
/* ⚠️ THE NAME WRAPS, IT IS NOT CUT AT ITS END (W13 repair round). An
   ellipsis on one line ate the end of a long name first, which is the
   extension: "AITEST-W13-CHK-faktura-vvs-reparati…" with no ".pdf" on a phone
   and at 768, while the server keeps the end on purpose (Files::safeName,
   C-06). It breaks anywhere, as the file list and the price card do. */
.fileline .fl-meta b{font-weight:600;color:var(--ink);display:block;line-height:1.3;
  overflow-wrap:anywhere}
.fileline .fl-meta span{font-size:10.5px;color:var(--text-3)}
.fileline .cbtn{flex-shrink:0}

/* The picture itself. A fixed frame so the thread does not jump about while
   each one arrives, and object-fit so nothing is stretched. */
.fileline.fl-image{align-items:flex-start}
.fileline .fl-thumb{
  width:96px;height:72px;flex-shrink:0;padding:0;
  border-radius:9px;overflow:hidden;background:#F2F3F6;
  display:grid;place-items:center;color:var(--text-3);
  border:1px solid var(--border-2);transition:all .15s;
}
.fileline .fl-thumb:hover{border-color:var(--brand-100);transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.fileline .fl-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.fileline .fl-thumb .fl-ph svg{width:16px;height:16px}
/* The two boxes a file row draws before (or instead of) its picture were the
   light theme's grey on the dark card: a white tile where a photo is still
   on its way (W-09). */
html.dark .fileline .fl-icon,html.dark .fileline .fl-thumb{background:#202734}

/* Larger. The modal supplies the frame, the header and Escape. */
.lightbox{display:flex;justify-content:center;padding:0}
.lightbox img{
  max-width:100%;max-height:70vh;object-fit:contain;
  border-radius:var(--r-md);background:#F2F3F6;
}

@media (max-width:920px){
  .fileline{margin-left:0;width:100%}
  .fileline .fl-thumb{width:78px;height:60px}
}

/* ============ the planning board (provider desk, Wave 3 §6 first slice) ============
 * Seven days across, one row per person. Scrolls sideways inside its own box
 * rather than the page, like every wide table here. */
.board{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-sm);overflow-x:auto}
/* Seven days beside the names inside a 1360px window (about 1060px of page):
   at 170 + 7 × 150 the Saturday column sat past the right edge of a box with
   nothing to say it scrolled. Narrower screens scroll the board as before. */
.board-head,.board-row{display:grid;grid-template-columns:140px repeat(7,minmax(118px,1fr));min-width:966px}
.board-head{border-bottom:1px solid var(--border)}
.board-head span{padding:10px 12px;font-size:11px;color:var(--text-2);text-transform:uppercase;letter-spacing:.05em;display:flex;flex-direction:column;gap:2px}
.board-head span small{text-transform:none;letter-spacing:0;color:var(--text-3);font-size:11px}
.board-head .today b{color:var(--brand)}
.board-row{border-bottom:1px solid var(--border)}
.board-row:last-child{border-bottom:0}
.board-who{padding:12px;display:flex;flex-direction:column;gap:3px;border-right:1px solid var(--border);font-size:13px;min-width:0}
.board-who small{color:var(--text-3);font-size:11.5px}
.board-cell{padding:8px;display:flex;flex-direction:column;gap:6px;border-right:1px solid var(--border-2);min-height:58px;min-width:0}
.board-cell:last-child{border-right:0}
.board-card{display:flex;flex-direction:column;gap:2px;align-items:flex-start;text-align:left;width:100%;background:var(--brand-50);border:1px solid var(--brand-100);border-radius:var(--r-sm);padding:7px 9px;font:inherit;color:var(--text);cursor:pointer;min-width:0}
.board-card:hover,.board-card:focus-visible{border-color:var(--brand);outline:none}
.board-card time{font-size:11px;color:var(--brand);font-weight:600}
.board-card b{font-size:11.5px}
.board-card span{font-size:12px;line-height:1.3}
.board-card small{font-size:11px;line-height:1.3;color:var(--text-3)}
/* Two lines each before the dots: seven days in a 1360px window leave a card
   about 115px, which cut every title at fifteen characters on one line. */
/* ⚠️ A LONG WORD WAS CUT AT WHATEVER LETTER REACHED THE EDGE (Q-07, owner
   decision 5 October 2026): "personalerum" over "met". The columns keep
   their width, so the board still fits a 1360px window, and the word is
   broken with a hyphen where the language breaks it: the browser's own
   hyphenation, in the language the page is read in (I18n.boot sets `lang` on
   the page). overflow-wrap stays for a word no dictionary knows, and for a
   browser with no dictionary for the language, where it is as it was. */
.board-card span,.board-card small{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto;max-width:100%}
.board-empty{padding:34px 20px;text-align:center;color:var(--text-2);font-size:13px}
.board-note{margin-top:14px;font-size:12.5px;color:var(--text-2)}
.board-note a{color:var(--brand)}

/* --------------------------------------------------------------------------
   The store's profile (WP20): address, phone, contact, hours, the way in.
   One card in the desk's and head office's case rail, on the store's page
   and at the top of the job a craftsman opens on a phone, where the links
   are the thing he taps: big enough for a thumb, the address and each number
   on their own line.
   -------------------------------------------------------------------------- */
.store-card .store-name{font-weight:700;color:var(--ink);font-size:13.5px;margin-bottom:4px}
.store-card .kv{align-items:flex-start}
.store-card .kv .v{display:flex;flex-direction:column;align-items:flex-end;gap:2px;min-width:0;overflow-wrap:anywhere}
.store-card .kv .v a{color:var(--link);text-decoration:none;font-weight:650}
.store-card .kv .v a:hover{text-decoration:underline}
/* And a number or an address to reach somebody in any other details row (the
   contact on a case, the poster's reporter), which were the browser's own
   underlined blue. */
.kv .v a[href^="tel:"],.kv .v a[href^="mailto:"]{color:var(--link);text-decoration:none;font-weight:650}
.kv .v a[href^="tel:"]:hover,.kv .v a[href^="mailto:"]:hover{text-decoration:underline}
.store-card .store-hour{font-weight:600}
.store-card .store-hour.note{font-weight:500;color:var(--text-2)}
.store-card .store-note{display:grid;gap:2px;font-size:12.5px;line-height:1.5;padding:8px 0 2px;border-top:1px solid var(--border-2);color:var(--text-2);overflow-wrap:anywhere}
.store-card .store-note b{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-3)}
.store-card .store-note.key b{color:var(--amber)}
.thread > .store-card{margin-bottom:14px}
.tt b .chip{margin-right:6px;vertical-align:1px}
.sub-due.red{color:var(--red);font-weight:650}
.sub-due.amber{color:var(--amber);font-weight:650}
@media (max-width:640px){
  .store-card .kv{flex-direction:column;gap:2px}
  .store-card .kv .v{align-items:flex-start;text-align:left}
  .store-card .kv .v a{display:inline-block;padding:4px 0;font-size:15px}
}

/* ⚠️ A PHONE HAD TO SCROLL EVERY LIST SIDEWAYS TO READ THE ONE THING IN IT
   THAT SAYS WHAT TO DO (WP20, audit L12-05). The rule above keeps a desktop
   table whole by making it 620px wide and scrollable, so on a 375px phone
   the status chip of a craftsman's job, and the amount on an approval, sat
   off screen. A list marked `cards` turns into cards under 640px instead:
   the cell marked data-col="ref" and the one marked "status" share the first
   line, everything else stacks below it at full width, the title first. */
@media (max-width:640px){
  .tbl.cards{overflow-x:visible}
  /* Head office's list is cards here too, and its 920px floor (the sideways
     table above) made each card 920px wide: the status chip sat off screen
     and a long title ran past the edge instead of wrapping (F-009). */
  .tbl.cards .hqlist{min-width:0}
  .tbl.cards .trow-h{display:none}
  .tbl.cards .trow[style*="grid-template-columns"]{
    grid-template-columns:minmax(0,1fr) auto!important;min-width:0;gap:4px 10px;padding:12px 14px;align-items:center
  }
  .tbl.cards .trow > *{grid-column:1/-1;order:1}
  .tbl.cards .trow > [data-col="ref"]{grid-column:1;order:-2}
  .tbl.cards .trow > [data-col="status"]{grid-column:2;order:-1;justify-self:end}
  .tbl.cards .trow > [data-col="title"]{order:0}
  .tbl.cards .trow > [data-col="hide"]{display:none}
  /* A figure that was told apart by its column says what it is once the
     heading row is gone: "I alt · 8.000 kr." over "Udestående · 8.000 kr."
     on an invoice (W-01). */
  .tbl.cards .trow > [data-k]{font-size:12px}
  .tbl.cards .trow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* ⚠️ THE CATEGORY REGISTER ON A PHONE WAS A 620px TABLE WITH 598px OF FIXED
   COLUMNS (F-058). The name got what was left, about 20px, so it wrapped one
   word per line over the code, "RÆKKEFØLGE" ran into "KATEGORI", and "Redigér"
   and "Arkivér" sat a screen and a half to the right. Under 640px a row is a
   card: the two arrows beside the name, the code and the count under it, the
   buttons on a line of their own.
   And it is a card up to 1160px, not only on a phone: the fixed columns leave
   the name under 180px on anything narrower (46px at 1024 beside the menu,
   56px at 768), where it wrapped one word per line and "KATEGORI" ran into
   "KODE". */
@media (max-width:1160px){
  .tbl .trow-h.catreg{display:none}
  .tbl .trow.catreg[style*="grid-template-columns"]{
    grid-template-columns:auto minmax(0,1fr)!important;min-width:0;gap:4px 12px;padding:12px 14px;align-items:start
  }
  .trow.catreg > *{grid-column:2}
  .trow.catreg > .cat-move{grid-column:1;grid-row:1/span 3}
  .trow.catreg > .cat-move:empty{display:none}
  .trow.catreg > .cat-act{grid-column:1/-1;justify-content:flex-start!important;margin-top:4px}
}
/* The desk's inbox as cards (4 October walk): its seven columns hold 448px of
   fixed tracks, so on a phone titles wrapped a word a line and the page ran
   to 15.800px for forty cases. The first line is the tick, the reference, the
   priority and the status; the title, the customer and who has it follow.

   ⚠️ NOT ONLY ON A PHONE. Up to 1180px the title column is under 150px (with
   the sidebar beside it at 1000px it is 68px, and at 768px 84px), so the
   table scrolled sideways in its box with three words to a line. It is cards
   up to there and a table above. The header row goes, except its tick, which
   stays with its words so "select every case shown" is still one press. */
.tbl.inbox .trow-h .pick-all{display:none}
@media (max-width:1180px){
  .tbl.cards.inbox{overflow-x:visible}
  .tbl.cards.inbox .trow-h[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .tbl.cards.inbox .trow-h > span{display:none}
  .tbl.cards.inbox .trow-h > span:first-child:not(:empty){display:flex;align-items:center;gap:10px;padding:10px 14px}
  .tbl.cards.inbox .trow-h .pick-all{display:inline;cursor:pointer}
  .tbl.cards.inbox .trow[style*="grid-template-columns"]{
    grid-template-columns:auto auto minmax(0,1fr) auto!important;min-width:0;gap:4px 0;padding:12px 14px;align-items:center
  }
  .tbl.cards.inbox .trow > *{grid-column:1/-1;order:1}
  /* The space after the tick and the reference is theirs, not the grid's: a
     reader with no ticks has an empty first cell, and a gap after nothing
     pushed the reference in from the title's edge. */
  .tbl.cards.inbox .trow > [data-col="pick"]{grid-column:1;order:-4}
  .tbl.cards.inbox .trow > [data-col="pick"]:not(:empty){margin-right:10px}
  .tbl.cards.inbox .trow > [data-col="ref"]{grid-column:2;order:-3;margin-right:10px}
  .tbl.cards.inbox .trow > [data-col="priority"]{grid-column:3;order:-2}
  .tbl.cards.inbox .trow > [data-col="status"]{grid-column:4;order:-1;justify-self:end}
  .tbl.cards.inbox .trow > [data-col="title"]{order:0}
  .tbl.cards.inbox .trow > [data-col="where"] b{display:inline;font-weight:600;font-size:12px;color:var(--text-2)}
  .tbl.cards.inbox .trow > [data-col="where"] b::after{content:" · ";color:var(--text-3)}
}
/* ⚠️ THE PEOPLE LIST AND THE ROLLOUT, THE SAME WAY (W-01). People has 576px of
   fixed columns and the rollout 648, each before a gap, so the columns that
   hold the name, the e-mail and the store got what was left: 0px on a phone
   and 15px at 1024. Every word in them stood one letter to a line, a row was
   700 to 960px tall and the people page 8.500px.
   A row is a card with the tick and the name first, up to the width where
   the table's own columns can hold what goes in them again: 1440px for
   People and 1340px for the rollout (a name column of 85px; it has two more
   fixed columns). People stopped at 1280 at first, where a name has 100px,
   but the e-mail beside it had 117, and 148 at 1360: an address stood on
   three or four lines right above the width where the card gives it one.
   From 1441 it has 179px. Between a phone and there it is two or three short
   columns (who and how to reach them beside what they may see; a store and
   its state beside its six figures); on a phone everything is one column and
   the buttons go under it. A figure that was told apart by its column says
   what it is (data-k, the column's own heading). The heading row goes,
   except its tick, which keeps its words. */
.trow-h.perow .pick-all,.trow-h.rorow .pick-all{display:none}
@media (max-width:1440px){
  .tbl .trow-h.perow[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .trow-h.perow > span{display:none}
  .trow-h.perow > span:first-child:has(> input){display:flex;align-items:center;gap:10px;padding:10px 14px}
  .trow-h.perow .pick-all{display:inline;cursor:pointer}
  .tbl .trow.perow[style*="grid-template-columns"]{
    grid-template-columns:auto minmax(0,1fr) minmax(0,1fr) 150px!important;min-width:0;gap:3px 0;padding:12px 14px;align-items:start
  }
  /* A width on the tick, not a gap after it: most people have no tick (they
     are signed in already), and their names still start where the others'
     do. */
  .trow.perow > [data-col="pick"]{grid-column:1;grid-row:1/span 3;width:30px}
  .trow.perow > [data-col="title"]{grid-column:2;grid-row:1}
  .trow.perow > [data-col="mail"]{grid-column:2;grid-row:2/span 2}
  .trow.perow > [data-col="role"]{grid-column:3;grid-row:1;padding-left:16px}
  .trow.perow > [data-k]{grid-column:3;grid-row:2;padding-left:16px}
  .trow.perow > [data-last-active]{grid-row:3}
  .trow.perow > [data-col="act"]{grid-column:4;grid-row:1/span 3}
  .trow.perow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
@media (max-width:1340px){
  .tbl .trow-h.rorow[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .trow-h.rorow > span{display:none}
  .trow-h.rorow > span:first-child:has(> input){display:flex;align-items:center;gap:10px;padding:10px 14px}
  .trow-h.rorow .pick-all{display:inline;cursor:pointer}
  .tbl .trow.rorow[style*="grid-template-columns"]{
    grid-template-columns:auto minmax(0,1fr) minmax(0,1fr) minmax(0,1fr)!important;min-width:0;gap:5px 0;padding:12px 14px;align-items:start
  }
  .trow.rorow > [data-col="pick"]{grid-column:1;grid-row:1/span 3;width:30px}
  .trow.rorow > [data-col="title"]{grid-column:2;grid-row:1}
  .trow.rorow > [data-col="state"]{grid-column:2;grid-row:2/span 2}
  /* The one-line figures share the first row, so the name stands right over
     its state and not over a gap as tall as the case count's three lines. */
  .trow.rorow > [data-col="live"]{grid-column:3;grid-row:1}
  .trow.rorow > [data-col="poster"]{grid-column:3;grid-row:2}
  .trow.rorow > [data-col="manager"]{grid-column:3;grid-row:3}
  .trow.rorow > [data-col="self"]{grid-column:4;grid-row:1}
  .trow.rorow > [data-col="cases"]{grid-column:4;grid-row:2}
  .trow.rorow > [data-col="latest"]{grid-column:4;grid-row:3}
  .trow.rorow > [data-k]{padding-left:16px}
  .trow.rorow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
@media (max-width:640px){
  .tbl .trow.perow[style*="grid-template-columns"],
  .tbl .trow.rorow[style*="grid-template-columns"]{grid-template-columns:auto minmax(0,1fr)!important}
  .trow.perow > [data-col="pick"]{grid-row:1/span 5}
  .trow.rorow > [data-col="pick"]{grid-row:1/span 8}
  .tbl .trow.perow > :not([data-col="pick"]),.tbl .trow.rorow > :not([data-col="pick"]){grid-column:2;grid-row:auto;padding-left:0}
  .trow.perow > [data-col="act"]{justify-content:flex-start!important;margin-top:5px}
}
/* ⚠️ HEAD OFFICE'S CASES, ITS INVOICES AND THE STORE REGISTER, THE SAME WAY
   (V-17, V-20). The round before let the two widest lists keep a floor and
   scroll in their own box between a phone and a desk: at 1024 a row of cases
   was 920px in a box of 728, so its status, the one thing in a row that says
   what to do, sat half cut at the edge or out of sight, and on a phone the
   register showed a store's name and its groups with nothing to say there
   was more to the right. The invoices kept to their box by giving who it is
   from 67px, which cut "Ejendomsservice" in two.
   Up to the width where its own columns hold what goes in them, a case and
   an invoice are two lines (what it is and how it stands above; where, who
   and when below) and a store is a card like a row of the rollout: the cases
   up to 1280px, where a title has 170px again, the invoices to 1100 and the
   register to 1340. Nothing scrolls sideways and no heading is needed: a
   figure that was told apart by its column says what it is (data-k). */
.trow-h.brow .pick-all{display:none}
@media (min-width:641px) and (max-width:1280px){
  .hqlist .trow-h{display:none}
  .tbl .hqlist .trow[style*="grid-template-columns"]{
    grid-template-columns:84px minmax(0,1.3fr) minmax(0,1fr) 200px!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .hqlist .trow > [data-col="ref"]{grid-column:1;grid-row:1}
  .hqlist .trow > [data-col="title"]{grid-column:2/4;grid-row:1}
  .hqlist .trow > [data-col="status"]{grid-column:4;grid-row:1;justify-self:end;text-align:right}
  .hqlist .trow > [data-col="priority"]{grid-column:1;grid-row:2}
  .hqlist .trow > [data-col="meta"]{grid-column:2;grid-row:2}
  .hqlist .trow > [data-col="holder"]{grid-column:3;grid-row:2}
  .hqlist .trow > [data-col="deadline"]{grid-column:4;grid-row:2;justify-self:end;text-align:right;align-items:flex-end}
}
/* Head office's and the customer's lists (I-03, I-04): "Delvist betalt" under
   what is left, and a credit note's missing due date as the product's drawn
   none-mark, the one the tender rows use (.bgt-row.bid .bv.mark). */
.trow.ivrow .ivpart{display:block;font-size:11px;font-weight:500;color:var(--text-3)}
.trow.ivrow .mark::before{content:"";display:inline-block;width:10px;height:2px;border-radius:1px;background:currentColor;vertical-align:middle}
@media (min-width:641px) and (max-width:1100px){
  .tbl .trow-h.ivrow{display:none}
  .tbl .trow.ivrow[style*="grid-template-columns"]{
    grid-template-columns:120px minmax(0,1.3fr) minmax(0,1fr) 130px!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .trow.ivrow > [data-col="ref"]{grid-column:1;grid-row:1}
  .trow.ivrow > [data-col="title"]{grid-column:2;grid-row:1}
  .trow.ivrow > [data-col="case"]{grid-column:2;grid-row:2}
  .trow.ivrow > [data-col="total"]{grid-column:3;grid-row:1}
  .trow.ivrow > [data-col="due"]{grid-column:3;grid-row:2}
  .trow.ivrow > [data-col="status"]{grid-column:4;grid-row:1;justify-self:end}
  /* Both figures in the size of a row's small print (I-07): the desk's
     "Outstanding" is not a .mut2 like "Total" above it, since what is owed
     stands in bold, and its label was drawn a size larger than the other. */
  .trow.ivrow > [data-k]{font-size:12px}
  .trow.ivrow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* The desk's list with a draft in view has one thing more on a draft's row,
   "Slet kladde" (R-09), and the table says so (data-ivacts). As a table the
   button has a column of its own after the status. From 1241px that column
   and its gap are 116px taken from who is billed and the case, which have
   them to give there.
   ⚠️ FROM 1101 TO 1240 THEY DO NOT (a name would be left 43px at 1101), and
   the first build drew the list as two lines there, 83px a row where every
   tab without a draft was a table of 46 (repair round). The 116px come from
   the three columns that are wider than anything that stands in them: the
   number (64px; F-1234567 is 61, its heading 53), the total (96; six
   figures before the comma are 94 in English, 83 in Danish) and what is
   outstanding (108; the same in bold is 106), and 4 from the button's own,
   which "Delete draft" fills. A name and a case then have to the pixel
   what the six columns give them at the same width, so the list is a table
   from 1101px with or without a draft in it. Under that the button stands
   under the status, where the second of the two lines is empty; on a phone
   it is the card's last line (.tbl.cards). */
@media (min-width:1241px){
  .tbl[data-ivacts] .trow.ivrow[style*="grid-template-columns"],
  .tbl[data-ivacts] .trow-h.ivrow[style*="grid-template-columns"]{grid-template-columns:120px 1.4fr 1fr 130px 130px 140px 104px!important}
  .tbl[data-ivacts] .trow.ivrow > [data-col="act"]{justify-self:end}
}
@media (min-width:1101px) and (max-width:1240px){
  .tbl[data-ivacts] .trow.ivrow[style*="grid-template-columns"],
  .tbl[data-ivacts] .trow-h.ivrow[style*="grid-template-columns"]{grid-template-columns:64px 1.4fr 1fr 96px 108px 140px 100px!important}
  .tbl[data-ivacts] .trow.ivrow > [data-col="act"]{justify-self:end}
}
/* Written max-width first, so the two lines of every invoice list above stay
   the only block that opens with their query (a check reads that block). */
@media (max-width:1100px) and (min-width:641px){
  .tbl[data-ivacts] .trow.ivrow > [data-col="act"]{grid-column:4;grid-row:2;justify-self:end;margin-top:3px}
  /* With what is left as a column of its own (data-ivrest, I-03) it stands
     under the total, as the desk's does, and the due date under the status. */
  .tbl[data-ivrest] .trow.ivrow > [data-col="left"]{grid-column:3;grid-row:2}
  .tbl[data-ivrest] .trow.ivrow > [data-col="due"]{grid-column:4;grid-row:2;justify-self:end;text-align:right}
}
@media (max-width:640px){
  .tbl[data-ivacts] .trow.ivrow > [data-col="act"]{margin-top:6px}
}
@media (max-width:1340px){
  .tbl .trow-h.brow[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .trow-h.brow > span{display:none}
  .trow-h.brow > span:first-child:has(> input){display:flex;align-items:center;gap:10px;padding:10px 14px}
  .trow-h.brow .pick-all{display:inline;cursor:pointer}
  .tbl .trow.brow[style*="grid-template-columns"]{
    grid-template-columns:auto minmax(0,1.4fr) 168px minmax(0,1fr) auto!important;min-width:0;gap:5px 0;padding:12px 14px;align-items:start
  }
  .trow.brow > [data-col="pick"]{grid-column:1;grid-row:1/span 2;width:30px}
  .trow.brow > [data-col="title"]{grid-column:2;grid-row:1}
  .trow.brow > [data-col="groups"]{grid-column:2;grid-row:2}
  /* 168px: the chip that says what a store lacks, whole in English too
     ("Nobody responsible", 150px), and at the same place in every row. */
  .trow.brow > [data-col="ready"]{grid-column:3;grid-row:1;padding-left:16px}
  .trow.brow > [data-col="open"]{grid-column:3;grid-row:2}
  /* No readiness to stand under (a reader, the archived tab): the count
     takes the first line. */
  .trow.brow:not(:has(> [data-col="ready"])) > [data-col="open"]{grid-row:1}
  .trow.brow > [data-col="live"]{grid-column:4;grid-row:1}
  .trow.brow > [data-col="since"]{grid-column:4;grid-row:2}
  .trow.brow > [data-col="act"]{grid-column:5;grid-row:1/span 2;padding-left:16px}
  .trow.brow > [data-k]{padding-left:16px}
  .trow.brow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
@media (max-width:640px){
  .tbl .trow.brow[style*="grid-template-columns"]{grid-template-columns:auto minmax(0,1fr)!important}
  .trow.brow > [data-col="pick"]{grid-row:1/span 7}
  .tbl .trow.brow > :not([data-col="pick"]){grid-column:2;grid-row:auto;padding-left:0}
  .trow.brow > [data-col="act"]{justify-content:flex-start!important;margin-top:5px}
}
/* ⚠️ HEAD OFFICE'S SUPPLIERS, THE SAME WAY (Y-15). The last list that still
   scrolled in its box between a phone and a desk: 720px of table in a box of
   611 at 641px and of 625 at 921, and from there to 1280 a firm column so
   narrow that an e-mail address stood on four lines (buyer.js has the
   measurements). From 641 to 1280px a firm is a card like a store above:
   the tick, the firm and its contact, then what it covers, where, and how
   many it has been given, each saying its heading, then its rating, and
   how it stands in a last column of the width the table gave it, so it
   starts at the same place in every row. Under 641 it is the card every
   `cards` list is on a phone, as it was, and the count stays out of it; from
   1281 it is the table. The heading says data-h and not data-k: every
   `cards` list prints a data-k heading on a phone as well, and this list's
   phone card prints none.
   Three things on a phone are not as they were (the repair of Y-15). The
   firm gets what the chips that say how it stands leave over, and that can
   be less than the chips beside its name need: "Modtager ikke mails" and
   "Driftens eget firma", 150 and 142px, were cut inside the pill ("Modtager
   ikk") from 360 to 420px, where nobody can hover for the rest.
   · A firm that stands two ways at once ("Ikke inviteret" and "Sat på
     pause") had the two side by side, 221px of a card of 300 at 360px: 71px
     for the firm, and none at all beside an invitation with its date, so
     the name stood one letter to a line. The two stand one over the other;
     a firm with one chip is untouched.
   · The chips beside the name take two lines where one does not hold them,
     by what `.chip.wraps` says, written out because it is asked for on a
     phone only: from 641px the firm has 200px and nothing here applies. No
     margin after them either: 6px to the right of the last thing on a line
     made a chip that fitted take two lines.
   · The tick that chooses every firm was gone with the heading row. It
     stays, with its words, at every width under 1281. */
.trow-h.surow .pick-all{display:none}
@media (max-width:640px){
  .tbl.cards .trow.surow > [data-col="jobs"]{display:none}
  .tbl.cards .trow.surow > [data-col="status"]:has(> .chip + .chip){display:flex;flex-direction:column;align-items:flex-end;gap:4px}
  .tbl.cards .trow.surow > [data-col="ref"] .chip{white-space:normal;height:auto;min-height:24px;padding:3px 10px;line-height:1.3;border-radius:12px;margin-right:0}
}
@media (max-width:1280px){
  .tbl .trow-h.surow[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .trow-h.surow > span{display:none}
  .trow-h.surow > span:first-child:has(> input){display:flex;align-items:center;gap:10px;padding:10px 14px}
  /* A reader has no tick, so nothing of the heading row is left to draw. */
  .tbl .trow-h.surow[style*="grid-template-columns"]:not(:has(input)){display:none}
  .trow-h.surow .pick-all{display:inline;cursor:pointer}
}
@media (min-width:641px) and (max-width:1280px){
  /* The last row takes what is left over: a firm with two chips under its
     name is taller than the four lines beside it, and without this the
     difference was shared out as gaps between those lines. */
  .tbl .trow.surow[style*="grid-template-columns"]{
    grid-template-columns:auto minmax(0,1.3fr) minmax(0,1fr) 186px!important;grid-template-rows:auto auto auto 1fr;
    min-width:0;gap:4px 0;padding:12px 14px;align-items:start
  }
  /* A width on the tick and not a gap after it, as in the lists above: a
     firm that already signs in has no tick and a reader has no tick column,
     and the name starts where it should for both. */
  .trow.surow > [data-col="pick"]{grid-column:1;grid-row:1/-1;width:30px}
  .trow.surow > [data-col="ref"]{grid-column:2;grid-row:1/-1}
  .trow.surow > [data-col="covers"]{grid-column:3;grid-row:1}
  .trow.surow > [data-col="area"]{grid-column:3;grid-row:2}
  .trow.surow > [data-col="jobs"]{grid-column:3;grid-row:3}
  .trow.surow > [data-col="rating"]{grid-column:3;grid-row:4}
  .trow.surow > [data-col="status"]{grid-column:4;grid-row:1/-1}
  .trow.surow > [data-col="ref"] ~ *{padding-left:16px}
  .trow.surow > [data-h]::before{content:attr(data-h) " · ";color:var(--text-3);font-weight:500}
}
/* And the groups under the register: four columns that kept a floor of 760px
   in a panel, so "Arkivér" was cut at the panel's edge on a tablet and out of
   sight on a phone. A group is its name over its kind and its count, with its
   two buttons beside them. */
@media (max-width:820px){
  .panel .trow-h.grprow{display:none}
  .panel .trow.grprow[style*="grid-template-columns"]{grid-template-columns:minmax(0,1fr) auto!important;min-width:0;gap:3px 12px;padding:10px 18px;align-items:start}
  .trow.grprow > [data-col="title"]{grid-column:1;grid-row:1}
  .trow.grprow > [data-col="kind"]{grid-column:1;grid-row:2}
  .trow.grprow > [data-col="count"]{grid-column:1;grid-row:3}
  .trow.grprow > [data-col="act"]{grid-column:2;grid-row:1/span 3}
  .trow.grprow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* The targets in the desk's service-level dialog (W-01): the urgency and the
   clock choice are 216px of a phone's 346, which left each minute field 47px,
   one digit of "1440" showing. On a phone the two figures share the row and
   the clock goes under them; its heading goes, the choice says what it is. */
@media (max-width:640px){
  .trow.sla-edit,.trow-h.sla-edit{grid-template-columns:70px minmax(0,1fr) minmax(0,1fr)!important}
  .trow.sla-edit > :nth-child(4){grid-column:2/-1}
  .trow-h.sla-edit > :nth-child(4){display:none}
  .trow.sla-edit .f-input,.trow.sla-edit .fsel,.trow.sla-edit select{width:100%!important;max-width:none}
}
/* ⚠️ THE QR POSTERS, THE SAME WAY (V-28). The tick, the state and the buttons
   are 414px before a gap, so the store, the code and the use got what was
   left: 40, 34 and 37px on a phone (the name on three lines, the 32-letter
   code five letters to a line, the buttons a screen to the right in a box
   with nothing saying it scrolls) and 79, 67 and 73px at 1024.
   Up to 1280px a row is a card: the store and its code beside the state and
   the use, the buttons on a line of their own under them; on a phone one
   column. The code says what it is (data-k, its column's heading), because
   32 letters with no heading over them are a riddle, and a store with no
   poster shows no use. 1280 and not 1180, where the other lists turn: at
   1181 the store had 136px, and a name of one long word was cut in two.
   From 1281 it is the table (172px for the store), and its rows have air:
   the buttons stack three high there and touched the line above and below.
   A label stands in from its store. */
.trow-h.porow .pick-all{display:none}
.trow.porow{padding-top:10px;padding-bottom:10px}
.trow.porow.polabel > [data-col="title"]{padding-left:14px}
@media (max-width:1280px){
  .tbl .trow-h.porow[style*="grid-template-columns"]{display:flex;min-width:0;padding:0}
  .trow-h.porow > span{display:none}
  .trow-h.porow > span:first-child{display:flex;align-items:center;gap:10px;padding:10px 14px}
  .trow-h.porow .pick-all{display:inline;cursor:pointer}
  .tbl .trow.porow[style*="grid-template-columns"]{
    grid-template-columns:30px minmax(0,1fr) minmax(0,1fr)!important;min-width:0;gap:4px 0;padding:12px 14px;align-items:start
  }
  .tbl .trow.porow.polabel[style*="grid-template-columns"]{padding-left:28px}
  .trow.porow.polabel > [data-col="title"]{padding-left:0}
  .trow.porow > [data-col="pick"]{grid-column:1;grid-row:1/span 3}
  .trow.porow > [data-col="title"]{grid-column:2;grid-row:1}
  .trow.porow > [data-col="token"]{grid-column:2;grid-row:2}
  .trow.porow > [data-col="state"]{grid-column:3;grid-row:1;padding-left:16px}
  .trow.porow > [data-col="usage"]{grid-column:3;grid-row:2;padding-left:16px}
  .trow.porow > [data-col="act"]{grid-column:2/-1;grid-row:3;justify-content:flex-start!important;margin-top:6px}
  .trow.porow > [data-k]::before{content:attr(data-k) " · ";font-size:12px;font-weight:500;color:var(--text-3)}
  .trow.porow > [data-none]{display:none}
}
@media (max-width:640px){
  .tbl .trow.porow[style*="grid-template-columns"]{grid-template-columns:30px minmax(0,1fr)!important}
  .trow.porow > [data-col="pick"]{grid-row:1/span 5}
  .tbl .trow.porow > :not([data-col="pick"]){grid-column:2;grid-row:auto;padding-left:0}
}
/* Where the register's box is under some 710px wide (a small tablet, and a
   window just wide enough to bring the menu back beside the page), the five
   columns leave the name 135 to 190px, and a store named in one long word
   was cut in two. There the buttons go under the card and the name has
   their room. */
@media (min-width:641px) and (max-width:740px),(min-width:921px) and (max-width:1010px){
  .tbl .trow.brow[style*="grid-template-columns"]{grid-template-columns:auto minmax(0,1.4fr) 168px minmax(0,1fr)!important}
  .trow.brow > [data-col="act"]{grid-column:2/-1;grid-row:3;justify-content:flex-start!important;padding-left:0;margin-top:4px}
  .trow.brow > [data-col="act"]:empty{display:none}
}
/* ⚠️ HEAD OFFICE'S TENDERS, WHERE THEIR BOX IS NARROWER THAN THEIR FLOOR
   (X-06). The list says a floor of 720px, which the box has at 768 and at
   1024. Under 750 it has less (670px at a 700px window), and again from 921,
   where the menu is back beside the page, to 1016 (704px at 1000): there the
   table scrolled sideways in its box and "Lukket · skal afgøres", the one
   thing in a row that says what to do, was cut at the edge.
   In those two bands a tender is two lines, as head office's cases are:
   number, title and status above, the location and the deadline below, the
   deadline saying what it is (data-k). Nothing scrolls. Outside them it is
   the table it was. */
@media (min-width:641px) and (max-width:760px),(min-width:921px) and (max-width:1020px){
  .tdlist .trow-h{display:none}
  .tbl .tdlist .trow[style*="grid-template-columns"]{
    grid-template-columns:84px minmax(0,1.3fr) minmax(0,1fr) auto!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .tdlist .trow > [data-col="ref"]{grid-column:1;grid-row:1}
  .tdlist .trow > [data-col="title"]{grid-column:2/4;grid-row:1}
  .tdlist .trow > [data-col="status"]{grid-column:4;grid-row:1;justify-self:end}
  .tdlist .trow > [data-col="meta"]{grid-column:2;grid-row:2}
  .tdlist .trow > [data-k]{grid-column:3/5;grid-row:2;justify-self:end;text-align:right}
  .tdlist .trow > [data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* And the same two bands for the two other lists of cases that say a floor of
   720px, the store's own and the plain customer's: the priority, the last
   column, was cut at the edge of a box that scrolled. Number, title and
   status above; the category (the store's list) or the location (the
   customer's) and the priority below. */
@media (min-width:641px) and (max-width:760px),(min-width:921px) and (max-width:1020px){
  .tbl .trow-h.employee-case-list-h,.cslist .trow-h{display:none}
  .tbl .trow.employee-case-list-row[style*="--floor"],
  .tbl .cslist .trow[style*="grid-template-columns"]{
    grid-template-columns:84px minmax(0,1fr) auto!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .employee-case-list-row > .tid,.cslist .trow > [data-col="ref"]{grid-column:1;grid-row:1}
  .employee-case-list-row > .tt,.cslist .trow > [data-col="title"]{grid-column:2;grid-row:1}
  .employee-case-list-row > .case-row-status,.cslist .trow > [data-col="status"]{grid-column:3;grid-row:1;justify-self:end}
  .employee-case-list-row > .mut2,.cslist .trow > [data-col="meta"]{grid-column:2;grid-row:2}
  .employee-case-list-row > .case-row-priority,.cslist .trow > [data-col="meta"]:last-child{grid-column:3;grid-row:2;justify-self:end}
}
/* ⚠️ THE FIRM'S JOBS, THE SAME WAY (X-17). Its list keeps 646px for the
   number, the customer, the time and where it stands, and a column that has
   a largest size (where it stands, up to 230px) is filled before the title
   gets a pixel more than its 150: up to 1100px wide a title stood on three
   or four lines beside a deadline that on "Afsluttede" and "Mangler pris"
   only ever says "Ikke angivet", and where the box was under 712px the list
   scrolled sideways in it.
   From 641 to 1180px a job is two lines: number, what it is and where it
   stands above, the customer and the time below, the time with the wider
   share ("Udført senest man. 12. okt., 14.15" is 195px). A row with no time
   to give shows none (data-none); on a phone and from 1181px, where the
   title has 200px again, nothing is changed. */
@media (min-width:641px) and (max-width:1180px){
  .sjlist .trow-h{display:none}
  .tbl .sjlist .trow[style*="grid-template-columns"]{
    grid-template-columns:84px minmax(0,1fr) minmax(0,1.6fr) minmax(160px,230px)!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .sjlist .trow > [data-col="ref"]{grid-column:1;grid-row:1}
  .sjlist .trow > [data-col="title"]{grid-column:2/4;grid-row:1}
  .sjlist .trow > [data-col="status"]{grid-column:4;grid-row:1/span 2}
  .sjlist .trow > [data-col="meta"]{grid-column:2;grid-row:2}
  .sjlist .trow > .sub-due{grid-column:3}
  .sjlist .trow > [data-none]{display:none}
}
/* ⚠️ THE DECISION TRAIL, LAID OUT FOR THE WIDTH TOO (X-07). Its floor (730px,
   above) kept the sentence readable by letting the table scroll in its box,
   so on a phone "Hvem" and "Handler som" were out of sight with nothing to
   say they were there: a log of what happened, and never who did it.
   On a phone an event is a card by the marks every list uses (.tbl.cards):
   when and acting as on the first line, the sentence with its key, then who,
   saying its heading. Where the box is narrower than the table (the same two
   bands as the tenders) it is two lines: when over who, the sentence with
   its key, acting as. From there it is the table it was.
   The pill says its heading wherever the heading row is gone, as who does on
   the card ("Handler som", data-k on its cell): in front of it on a phone,
   over it in the two bands, where a heading in front would take 80px from
   the sentence. On the card the time keeps its own width and the pills wrap
   in the rest: with the heading in front, two pills are wider than the card
   and would have left the time 20px. */
@media (max-width:640px){
  .tbl.cards .trow.aurow[style*="grid-template-columns"]{grid-template-columns:auto minmax(0,1fr)!important}
  .tbl.cards .trow.aurow > [data-col="status"]{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:4px}
}
@media (min-width:641px) and (max-width:760px),(min-width:921px) and (max-width:1020px){
  .tbl .trow-h.aurow[style*="grid-template-columns"]{display:none}
  .tbl .trow.aurow[style*="grid-template-columns"]{
    grid-template-columns:150px minmax(0,1fr) auto!important;min-width:0;gap:3px 14px;padding:10px 18px;align-items:start
  }
  .trow.aurow > [data-col="ref"]{grid-column:1;grid-row:1}
  .trow.aurow > [data-k]:not([data-col]){grid-column:1;grid-row:2}
  .trow.aurow > .tt{grid-column:2;grid-row:1/span 2}
  .trow.aurow > [data-col="status"]{grid-column:3;grid-row:1/span 2;justify-self:end;text-align:right}
  .trow.aurow > [data-col="status"]::before{content:attr(data-k);display:block;margin-bottom:2px;font-size:12px;line-height:14px;font-weight:500;color:var(--text-3)}
}
/* ⚠️ INSIGHT'S "HVER AFDELING", THE SAME WAY (C-01). It is a list of stores
   and not a matrix, and it kept a 930px floor and scrolled in its card from
   a phone up to 1225px: the name got the 58px that were left, three and
   four lines of it, and what was invoiced stood past the card's edge.
   Under 640px a store is a card: its name whole on the first line and the
   figures under it, each with its heading in front (data-k). The counts
   stand two to a line in two even columns, and the two sums have a line
   each. A pair is never broken in two: one that is too long for half the
   card ("Frister overholdt · Ikke angivet") takes a line of its own, which
   is why the card is a wrapping row here and not a grid.
   From 641 to 1340px, the width up to which the same stores are cards in
   their own register, it is a table of five figures: the four the card's
   own line says it shows (what came in, what got done, what the promises
   held and what was invoiced) and what is open now. The other three (the
   deadlines missed, the typical time and the firms' final prices) stand on
   a line under the figures with their headings in front: every figure in
   sight and none behind a scroll. Which five are columns is a choice made
   here and not the guide's: its chapter on Indsigt counts a typical time
   among a store's figures too, and that one stands on the line under. The
   name has 150px at the least, and the five columns take the widths they
   have in the whole table as soon as there is room.
   From 1341px it is the nine columns it always was, which leave the name
   its 150px from there on too: 173px, and 156 where a scrollbar takes 17px
   of the window. The table of five stopped at 1280px at first, and at 1281
   a name went from 438px to the 113 that nine columns leave it there, a
   long one from two lines to seven. */
.insrow > .fold{display:none}
@media (max-width:640px){
  .panel .trow-h.insrow{display:none}
  .panel .trow.insrow{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px 12px;min-width:0;padding:12px 18px}
  .trow.insrow > .tt{flex:0 0 100%}
  /* Half the card less half the gap, and half a pixel more off, so that two
     of them and the gap never come to a hair over the whole line. */
  .trow.insrow > [data-k]{flex:1 1 calc(50% - 6.5px);min-width:max-content;max-width:100%;white-space:nowrap}
  .trow.insrow > [data-k].sum{flex-basis:100%}
  .trow.insrow > [data-k]::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
@media (min-width:641px) and (max-width:1340px){
  .panel .trow.insrow[style*="grid-template-columns"],
  .panel .trow-h.insrow[style*="grid-template-columns"]{
    grid-template-columns:minmax(150px,1fr) minmax(64px,80px) minmax(44px,80px) minmax(56px,80px) minmax(74px,100px) minmax(104px,110px)!important;min-width:0
  }
  .insrow > [data-col="fold"]{display:none}
  /* Four figures as columns for a reader with no invoiced figure (M-02):
     the name takes the width the fifth had. */
  .panel .trow.insrow.noinv[style*="grid-template-columns"],
  .panel .trow-h.insrow.noinv[style*="grid-template-columns"]{
    grid-template-columns:minmax(150px,1fr) minmax(64px,80px) minmax(44px,80px) minmax(56px,80px) minmax(74px,100px)!important
  }
  /* Two lines beside a name that may take four: the figures sit on the foot
     of the first and the line under them on the head of the second, so the
     two stay together in the middle of the row. */
  .trow.insrow{row-gap:2px;padding-top:8px;padding-bottom:8px}
  .trow.insrow > .tt{grid-row:1/span 2}
  .trow.insrow > [data-k]{align-self:end}
  .trow.insrow > .fold{display:flex;flex-wrap:wrap;gap:0 14px;grid-column:2/-1;align-self:start}
  .trow.insrow > .fold > [data-k]::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* ⚠️ THE DESK'S RAPPORTER, "ALLE LOKATIONER" AND "PR. GRUPPE", THE SAME WAY
   (R-04). The same stores and figures as Insight's, and they kept an 820px
   floor and scrolled in their card up to about 1180px with nothing to say
   so: at 390 four columns showed, at 768 and 1024 "Faktureret" and its
   amount were cut at the card's edge, and a long name stood one word to a
   line. Laid out as .insrow above, at the same widths and for the same
   reasons: a card under 640px, every figure with its heading; up to 1340px
   five figures as columns (what came in, what got done, what is open, the
   deadlines held and what was invoiced) and the cells marked fold said on
   a line under them; from 1341px the whole table, the name 295px and more.
   A group's line under its figures says how many locations it has. */
.reprow > .fold{display:none}
@media (max-width:640px){
  .panel .trow-h.reprow{display:none}
  .panel .trow.reprow{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px 12px;min-width:0;padding:12px 18px}
  .trow.reprow > .tt{flex:0 0 100%}
  .trow.reprow > [data-k]{flex:1 1 calc(50% - 6.5px);min-width:max-content;max-width:100%;white-space:nowrap}
  .trow.reprow > [data-k].sum{flex-basis:100%}
  .trow.reprow > [data-k]::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
@media (min-width:641px) and (max-width:1340px){
  .panel .trow.reprow[style*="grid-template-columns"],
  .panel .trow-h.reprow[style*="grid-template-columns"]{
    grid-template-columns:minmax(150px,1fr) minmax(64px,80px) minmax(44px,80px) minmax(56px,80px) minmax(74px,100px) minmax(104px,110px)!important;min-width:0
  }
  .panel .trow.reprow.noinv[style*="grid-template-columns"],
  .panel .trow-h.reprow.noinv[style*="grid-template-columns"]{
    grid-template-columns:minmax(150px,1fr) minmax(64px,80px) minmax(44px,80px) minmax(56px,80px) minmax(74px,100px)!important
  }
  .reprow > [data-col="fold"]{display:none}
  .trow.reprow{row-gap:2px;padding-top:8px;padding-bottom:8px}
  .trow.reprow > .tt{grid-row:1/span 2}
  .trow.reprow > [data-k]{align-self:end}
  .trow.reprow > .fold{display:flex;flex-wrap:wrap;gap:0 14px;grid-column:2/-1;align-self:start}
  .trow.reprow > .fold > [data-k]::before{content:attr(data-k) " · ";color:var(--text-3);font-weight:500}
}
/* "Pr. person" on the same page (wave 13 repair): a card under 640px as
   above; from there its five figures are columns with no floor and no line
   under them, each as wide as its heading's longest word at the least
   ("SATISFACTION" is never cut), a time ("12 arbejdsdage") on two lines. */
@media (min-width:641px) and (max-width:1340px){
  .panel .trow.reprow.ppl[style*="grid-template-columns"],
  .panel .trow-h.reprow.ppl[style*="grid-template-columns"]{
    grid-template-columns:minmax(120px,1fr) minmax(62px,64px) minmax(84px,110px) minmax(84px,110px) minmax(86px,96px) minmax(74px,90px)!important
  }
  .trow.reprow.ppl > .tt{grid-row:auto}
  .trow.reprow.ppl > [data-k]{align-self:center}
}
/* ⚠️ THE SHORT LISTS IN A PANEL, ON A PHONE (V-34). The order per category
   and the trades on Fordeling, and the service plan's two lists, are rows of
   three or four columns. The floors above (620px in a .tbl, 760 in a panel)
   kept them whole by letting them scroll in their box, so on a phone the
   button read "Vælg fi" at the card's edge and "INTERVAL" was cut in two.
   Marked `stackrow`, a row has no floor (its columns are few and mostly
   free), and under 640px it is a card with no heading row: the cell marked
   "title" and the one marked "status" share the first line, "sub" and "act"
   the second, and every other cell takes a line of its own. A cell that was
   told apart by its column says the heading: data-k in front of a figure
   ("Interval · Årligt"), data-kh over a cell that holds a list of its own.
   `pair` keeps two such cells side by side, as the table had them: the
   standard order and the location's own. */
@media (max-width:820px){
  .tbl .trow.stackrow[style*="grid-template-columns"],.tbl .trow-h.stackrow[style*="grid-template-columns"],
  .panel .trow.stackrow[style*="grid-template-columns"],.panel .trow-h.stackrow[style*="grid-template-columns"]{min-width:0}
}
@media (max-width:640px){
  .trow-h.stackrow{display:none}
  .tbl .trow.stackrow[style*="grid-template-columns"],
  .panel .trow.stackrow[style*="grid-template-columns"]{
    grid-template-columns:minmax(0,1fr) auto!important;gap:5px 12px;padding:12px 18px;align-items:start
  }
  .tbl .trow.stackrow.pair[style*="grid-template-columns"]{grid-template-columns:minmax(0,1fr) minmax(0,1fr)!important}
  .trow.stackrow > *{grid-column:1/-1}
  .trow.stackrow > :empty{display:none}
  .trow.stackrow > [data-col="title"]{grid-column:1;grid-row:1}
  .trow.stackrow > [data-col="status"]{grid-column:2;grid-row:1;justify-self:end}
  .trow.stackrow > [data-col="sub"]{grid-column:1;grid-row:2}
  .trow.stackrow > [data-col="act"]{grid-column:2;grid-row:2;justify-self:end}
  .trow.stackrow.pair > [data-kh]{grid-column:auto}
  .trow.stackrow > [data-k]::before{content:attr(data-k) " · ";font-size:12px;font-weight:500;color:var(--text-3)}
  .trow.stackrow > [data-kh]::before{
    content:attr(data-kh);display:block;margin-bottom:2px;
    font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-3)
  }
}
/* The desk's filters on a phone (W-27): six or seven dropdowns are four rows
   there, and with the views above them the first case began at the fold. One
   control folds them away; it is not drawn on anything wider. Shut, it says
   how many are chosen and how many cases the list holds; open, the filter row
   under it says the count itself. */
.tbl.inbox .fold-toggle{display:none}
@media (max-width:640px){
  .tbl.inbox .fold-toggle{
    display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:6px 14px;
    border-top:1px solid var(--border-2);font-size:13px;color:var(--ink);text-align:left;
  }
  .tbl.inbox .fold-toggle b{font-weight:650}
  .tbl.inbox .fold-toggle b::after{
    content:"";display:inline-block;width:6px;height:6px;margin:0 0 3px 9px;
    border-right:1.7px solid var(--text-3);border-bottom:1.7px solid var(--text-3);transform:rotate(45deg);
  }
  .tbl.inbox .fold-toggle.open b::after{transform:rotate(-135deg);margin-bottom:-1px}
  .tbl.inbox .fold-toggle .n{font-size:12px;font-weight:650;color:var(--brand)}
  .tbl.inbox .fold-toggle.open .fcount{display:none}
  .tbl.inbox .fold-toggle:not(.open) + .filterbar{display:none}
  .tbl.inbox .fold-toggle + .filterbar{border-top:none;padding-top:2px}
}

/* ============ The approvals queue and the customer's own note (WP25) ============
   The queue carries what an approver decides on (L03-06): seven columns on a
   desk, and on a phone the reference and amount first, the title, then the
   limit, the wait and the budget as labelled lines. A row this reader may not
   answer says why in amber under the title.
   ⚠️ NOT ONLY ON A PHONE (W-01). The five fixed columns are 596px, so up to
   1180px, with the menu beside the page, the store and the title shared what
   was left: 9 and 15px at 1024, a letter to a line and a row 1.300px tall. */
.appr-queue-row .aq-amt{font-variant-numeric:tabular-nums}
.appr-queue-row .aq-block{display:block;margin-top:3px;color:var(--amber);font-weight:600}
@media (max-width:1180px){
  .appr-queue .trow-h{display:none}
  /* Not the 620px floor the other inline-grid tables keep on a phone
     (max-width:820px above): this row re-flows instead of scrolling. */
  .appr-queue-row{grid-template-columns:minmax(0,1fr) auto!important;gap:4px 10px;padding:12px;align-items:start;min-width:0!important}
  .appr-queue-row>.tid{grid-column:1;grid-row:1}
  .appr-queue-row>.aq-amt{grid-column:2;grid-row:1;text-align:right}
  .appr-queue-row>.tt{grid-column:1/3;grid-row:2}
  .appr-queue-row>.aq-store{grid-column:1/3;grid-row:3}
  .appr-queue-row>[data-k]{grid-column:1/3}
  .appr-queue-row>[data-k]:not(:empty)::before{content:attr(data-k) " · ";color:var(--text-3)}
}
.note-switch{display:flex;align-items:flex-start;gap:9px;margin:12px 0 0 44px;padding:9px 12px;border-radius:var(--r-sm);
  border:1px dashed var(--amber-br);background:var(--amber-bg);cursor:pointer;font-size:12.5px;line-height:1.4}
.note-switch input{margin-top:2px;accent-color:var(--amber-dot)}
.note-switch b{display:block;color:var(--amber);font-weight:650}
.note-switch span span{color:var(--text-2);font-size:11.5px}
.composer.is-note{border-color:var(--amber-br);background:var(--amber-bg)}
@media (max-width:640px){.note-switch{margin-left:0}}

/* ---------- a file on its way (api.js FogiDeskUpload, WP23) ----------
   The one panel every upload draws: the poster, the store console, the
   new-case dialog and the paperclip on a case. */
.upl{margin-top:10px;border:1px solid var(--border);border-radius:12px;padding:10px 12px;background:var(--card);text-align:left}
.upl.err{border-color:var(--red-br);background:var(--red-bg)}
.upl-h{display:flex;gap:8px;align-items:baseline;font-size:12.5px;color:var(--text-2);min-width:0}
.upl-h b{color:var(--ink);font-weight:650;flex:none}
.upl-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.upl-bar{height:6px;border-radius:3px;background:var(--border-2);overflow:hidden;margin-top:8px}
.upl-bar i{display:block;height:100%;width:0;background:var(--brand);border-radius:3px;transition:width .2s}
.upl-f{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:11.5px;color:var(--text-3);flex-wrap:wrap}
.upl-n{flex:1;min-width:0;font-variant-numeric:tabular-nums}
.upl-msg{font-size:12.5px;color:var(--red);margin-top:6px;line-height:1.5}
.qphoto .upl .btn{width:auto}
.upl-host:empty{display:none}

/* A video on a case plays where it is, once somebody asks for it. */
.fileline .fl-play{display:inline-flex;align-items:center;justify-content:center;gap:6px;width:78px;height:60px;border-radius:10px;border:1px solid var(--border);background:var(--bg);color:var(--text-2);font:inherit;font-size:11px;cursor:pointer;flex-shrink:0}
.fileline .fl-play svg{width:18px;height:18px}
.fileline .fl-play:hover{border-color:var(--brand-100);color:var(--brand)}
.fileline.fl-video{align-items:flex-start;flex-wrap:wrap}
.fileline video{display:block;width:100%;max-width:420px;max-height:320px;border-radius:10px;background:#000;margin-top:6px}
.fileline .fl-heic{border:0;background:none;padding:0;font:inherit;font-size:11.5px;font-weight:600;color:var(--brand);cursor:pointer;white-space:nowrap;flex-shrink:0}
.fileline .fl-heic:hover{text-decoration:underline}
.lightbox-note{display:flex;justify-content:space-between;gap:10px;align-items:center;font-size:12px;color:var(--text-3);padding:10px 16px 0}

/* ================= help, the written guide and the printed sheets (WP40) =================
   The guide reads like a document rather than a form: a list of chapters on
   the left, the chapter on the right at a comfortable measure, and a print
   stylesheet that takes the console away so what comes out of the printer is
   the chapter, or the whole guide, or one A4 sheet for a workshop, under the
   workspace's own mark. */

.doc-wrap + .doc-wrap{border-top:1px solid var(--border-2)}
.doc-wrap .doc + .doc{border-top:0}
.guide-video{display:block;width:100%;max-height:360px;border-radius:var(--r-md);background:#000;margin:4px 0 10px}

.guide-grid{display:grid;grid-template-columns:270px minmax(0,1fr);gap:16px;align-items:start}
@media (max-width:900px){.guide-grid{grid-template-columns:1fr}}
.guide-nav{position:sticky;top:76px;max-height:calc(100vh - 96px);display:flex;flex-direction:column}
.guide-list{overflow-y:auto;padding:4px 8px 12px}
.guide-aud{font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3);padding:12px 8px 4px}
.guide-item{display:block;width:100%;text-align:left;border:0;background:none;font:inherit;font-size:13px;color:var(--text);padding:7px 8px;border-radius:var(--r-sm);cursor:pointer;line-height:1.35}
.guide-item:hover{background:var(--brand-50)}
.guide-item.on{background:var(--brand-50);color:var(--brand);font-weight:600}
.guide-main{padding:22px 26px 20px}
.guide-article{max-width:680px}
.guide-article + .guide-article{margin-top:34px;padding-top:26px;border-top:1px solid var(--border)}
.guide-kicker{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--brand)}
.guide-article h2{font-family:var(--font-display);font-size:24px;font-weight:800;letter-spacing:-.02em;color:var(--ink);margin:4px 0 12px}
.guide-body{font-size:14px;line-height:1.65;color:var(--text)}
.guide-body h2{font-family:var(--font-display);font-size:16px;font-weight:700;color:var(--ink);margin:22px 0 6px}
.guide-body h3{font-size:14px;font-weight:700;color:var(--ink);margin:16px 0 4px}
.guide-body p{margin:0 0 10px}
.guide-body ul,.guide-body ol{margin:0 0 12px;padding-left:22px}
.guide-body li{margin:3px 0}
.guide-body strong{color:var(--ink);font-weight:650}
.guide-body a{color:var(--brand);text-decoration:underline;text-underline-offset:2px}
.guide-body .guide-note{margin:14px 0}
.guide-foot{margin-top:18px;font-size:11.5px;color:var(--text-3)}
.guide-actions{margin-top:14px;display:flex;gap:8px}
.guide-actions:empty{display:none}
.print-head{display:none}
.print-logo{height:28px;width:auto;max-width:160px;object-fit:contain}
/* The mark is the workspace's colour with its letters on it, and it prints
   as that: a browser leaves backgrounds off paper unless it is told, and
   white letters on no square at all are a blank corner (X-10). */
.print-initials{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;color:#fff;font-weight:800;font-size:12px;-webkit-print-color-adjust:exact;print-color-adjust:exact}

/* ---- the A4 sheet: paper on screen too, whatever the theme ---- */
.sheet-a4{background:#fff;color:#1B2430;width:100%;max-width:210mm;min-height:297mm;margin:0 auto 24px;padding:14mm 14mm 12mm;box-shadow:var(--shadow-md);border-radius:6px;font-size:12.5px;line-height:1.5;display:flex;flex-direction:column;gap:14px;box-sizing:border-box}
.sheet-a4 h2{font-family:var(--font-display);font-size:17px;font-weight:800;margin:0 0 8px;color:#0F1522}
.sheet-a4 h3{font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#5A6474;margin:0 0 6px}
.sheet-a4 .kv{padding:5px 0;font-size:12.5px}
.sheet-a4 .kv .k{color:#5A6474}
.sheet-a4 .kv .v{color:#0F1522;overflow-wrap:anywhere;min-width:0}
.sheet-a4 .kv + .kv{border-top:1px solid #E6E9EF}
.sheet-a4 .hint{color:#5A6474;font-size:11.5px}
.sheet-head{display:flex;justify-content:space-between;align-items:center;gap:18px;padding-bottom:12px;border-bottom:3px solid}
.sheet-mark{display:flex;align-items:center;gap:12px}
.sheet-mark .print-logo{height:44px;max-width:200px}
.sheet-mark .print-initials{width:44px;height:44px;font-size:16px;border-radius:10px}
.sheet-mark b{display:block;font-family:var(--font-display);font-size:20px;font-weight:800;color:#0F1522;line-height:1.15}
/* The line under the name, and only that: as `.sheet-mark span` this rule
   also reached the initials, which are a span, and wrote them grey on the
   brand colour (X-10). */
.sheet-mark div span{font-size:13px;color:#5A6474}
.sheet-login{display:flex;align-items:center;gap:10px;text-align:right}
.sheet-login span{display:block;font-size:10.5px;color:#5A6474;text-transform:uppercase;letter-spacing:.06em}
.sheet-login b{font-size:14px;color:#0F1522}
.sheet-qr{width:30mm;height:30mm;display:block}
.sheet-steps ol{margin:0;padding-left:20px;font-size:13.5px;line-height:1.55}
.sheet-steps li{margin:0 0 7px;padding-left:2px}
.sheet-steps strong{font-weight:700}
.sheet-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px}
.sheet-cols section,.sheet-system{border:1px solid #E6E9EF;border-radius:10px;padding:10px 12px}
.sheet-urgent{border-color:#F5D2CC !important;background:#FCEDEA}
.sheet-urgent h3{color:#BE2D20}
.sheet-big{font-family:var(--font-display);font-size:24px;font-weight:800;color:#0F1522}
.sheet-foot{margin-top:auto;display:flex;justify-content:space-between;gap:12px;font-size:10.5px;color:#5A6474;border-top:1px solid #E6E9EF;padding-top:8px}
/* ⚠️ THE SHEET IS A4 AND A PHONE IS NOT (V-16). It kept its 14 mm margins and
   its two columns at 390px, which left a value 16px to stand in: "5.000 kr."
   a digit to a line, the approver's name over ten lines, and the sign-in line
   outside the screen. On a narrow SCREEN the margins give way, the head and
   the boxes stack, and a value breaks between its words. Paper is not a
   screen: the sheet prints as it always has, from a phone as well. */
@media screen and (max-width:700px){
  .sheet-a4{padding:18px 16px 16px;min-height:0}
  .sheet-head{flex-direction:column;align-items:flex-start;gap:12px}
  .sheet-mark .print-initials{flex:none}
  .sheet-login{text-align:left}
  .sheet-cols{grid-template-columns:minmax(0,1fr)}
  .sheet-a4 .kv{align-items:flex-start}
  .sheet-a4 .kv .k{flex:none;max-width:45%}
  .sheet-a4 .kv .v{overflow-wrap:break-word}
  .sheet-foot{flex-direction:column;gap:2px}
}

/* ============ Skift testbruger · a test estate only ============
   Drawn by FogiDeskChrome.wireTestSwitch for a session the server marked
   test_estate, and for nobody else. Hazard stripes and a monospace face on
   purpose, the same in light and dark: nothing else in the product looks like
   this, so a screenshot with it in is never taken for a FogiDesk screen. In
   the flow above the topbar, so it pushes the page down and covers nothing,
   and sticky, so a screen scrolled half way down still says TEST. */
.test-bar{
  display:flex;align-items:center;gap:10px;flex-shrink:0;
  min-height:34px;padding:4px 26px;
  position:sticky;top:0;z-index:41;
  background:repeating-linear-gradient(135deg,#FFE066 0 14px,#FFD233 14px 28px);
  border-bottom:2px solid #1A1400;color:#1A1400;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;font-weight:700;line-height:1.25;
}
/* The console's own sticky bars start under the band. ⚠️ Only under the class
   wireTestSwitch puts on <html> with the band's measured height: without a
   test session neither exists and these two rules match nothing. */
html.test-estate .topbar{top:var(--test-bar-h,36px)}
html.test-estate .guide-nav{top:calc(76px + var(--test-bar-h,36px));max-height:calc(100vh - 96px - var(--test-bar-h,36px))}
.test-tag{
  flex-shrink:0;background:#1A1400;color:#FFE066;border-radius:4px;padding:3px 7px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;
}
/* Who you are is the point of the band: it wraps on a phone, never cut short. */
.test-who{flex:1;min-width:0;overflow-wrap:anywhere}
.test-btn{
  flex-shrink:0;min-height:26px;padding:0 12px;border:2px dashed #1A1400;border-radius:6px;
  background:#FFFDF2;color:#1A1400;font:inherit;font-weight:800;
}
.test-btn:hover{background:#fff}
/* The product's focus ring is a pale blue, about 2:1 on the yellow. Here it is
   the band's own ink with a yellow edge inside it, so one of the two shows on
   the stripes, on a white card and on a dark one. */
.test-btn:focus-visible,.test-acct:focus-visible,.test-panel .m-x:focus-visible{
  outline:3px solid #1A1400;outline-offset:2px;box-shadow:0 0 0 2px #FFE066;
}
.test-btn:focus-visible{background:#1A1400;color:#FFE066;border-style:solid;outline-offset:1px}
html.dark .test-acct:focus-visible{outline-color:#FFE066;box-shadow:0 0 0 2px #1A1400}
.test-panel .m-h{
  padding:12px 16px;border-bottom:2px solid #1A1400;border-radius:18px 18px 0 0;
  background:repeating-linear-gradient(135deg,#FFE066 0 14px,#FFD233 14px 28px);
}
.test-panel .m-h h3{color:#1A1400;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:15px;letter-spacing:0}
.test-panel .m-x{color:#1A1400}
.test-panel .m-b{padding-bottom:18px}
.test-note{font-size:12.5px;line-height:1.5;color:var(--text-2);margin:0 0 4px}
.test-group{display:flex;align-items:baseline;gap:8px;margin:14px 0 6px}
.test-group b{font-size:13px;font-weight:750;color:var(--ink)}
.test-group span{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-3)}
/* Two across where there is room, so the whole estate is on one screen. */
.test-accts{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:6px}
.test-acct{
  display:flex;align-items:center;gap:8px;width:100%;min-width:0;min-height:48px;padding:7px 11px;
  text-align:left;background:var(--card);border:1px solid var(--border);border-radius:10px;
}
.test-acct:not([disabled]):hover{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink)}
.test-acct[disabled]{cursor:default}
.test-acct[disabled]:not(.here):not(.busy){opacity:.55}
.test-acct.here{border:2px dashed #1A1400;background:#FFF8D6}
.test-acct-who{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.test-acct-who b,.test-acct-who span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.test-acct-who b{font-size:13.5px;font-weight:650;color:var(--ink)}
.test-acct-who span{font-size:12px;color:var(--text-2)}
.test-acct.here .test-acct-who b{color:#1A1400}
.test-acct.here .test-acct-who span{color:#5C4A00}
.test-acct-flag{
  flex-shrink:0;max-width:46%;text-align:right;color:#1A1400;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;
}
.test-acct:not(.here) .test-acct-flag{color:var(--text-2)}
/* What went wrong, in a strip that stays at the top of the sheet while the
   list scrolls under it. The list is taller than a phone, and a message that
   stayed above it was out of view for every account but the first few. At
   the top, because the product's own toast for a refusal is at the bottom. */
.test-err{
  position:sticky;top:0;z-index:1;
  margin:10px -20px 0;padding:10px 20px;
  background:var(--red-bg);border-top:1px solid var(--red-br);border-bottom:2px solid var(--red);color:var(--red);
  font-size:13px;font-weight:650;line-height:1.4;
}
.test-err[hidden]{display:none}
@media (max-width:920px){
  .test-bar{padding:4px 12px;gap:8px}
}
@media (max-width:640px){
  .test-panel .m-h{border-radius:16px 16px 0 0}
  .test-accts{grid-template-columns:minmax(0,1fr)}
}

@page{size:A4;margin:12mm}
@media print{
  html,body{background:#fff !important}
  html.dark{color-scheme:light}
  .side,.topbar,.no-print,.back,.toast,.skiplink,#menuBtn{display:none !important}
  .shell,.main{display:block !important;min-height:0 !important}
  #app,.view{padding:0 !important;margin:0 !important;animation:none !important}
  .rise{animation:none !important;opacity:1 !important;transform:none !important}
  .guide-grid{display:block}
  .guide-main{border:0 !important;box-shadow:none !important;padding:0 !important;background:#fff !important}
  .guide-article{max-width:none;break-inside:auto}
  .guide-article + .guide-article{break-before:page;border-top:0;margin-top:0;padding-top:0}
  .guide-body,.guide-article h2,.guide-body h2,.guide-body h3,.guide-body strong{color:#111 !important}
  .guide-body a{color:#111 !important;text-decoration:none}
  .print-head{display:flex;align-items:center;gap:10px;margin-bottom:12mm;font-size:11px;color:#555;border-bottom:1px solid #ddd;padding-bottom:4mm}
  .sheet-a4{box-shadow:none;border-radius:0;margin:0;padding:0;width:auto;max-width:none;height:272mm;min-height:0;overflow:hidden;break-after:avoid}
}

/* pb-invoice · Abonnement */
/* The menu entry waits hidden until the server says there is a subscription
   to show; display:flex above would otherwise beat the browser's [hidden]. */
.nav-item[hidden]{display:none}

/* TD-SUP: the desk's supplier register, using the ordinary table and theme tokens. */
[data-td-suppliers] .trow,[data-td-suppliers] .trow-h{grid-template-columns:minmax(140px,1.2fr) minmax(180px,1.5fr) minmax(110px,1fr) 75px minmax(170px,1.1fr)}
[data-td-suppliers] .tbl-toolbar{align-items:flex-end}
[data-td-suppliers] .tbl-toolbar .f-group{margin:0;flex:1 1 160px;min-width:0}
[data-td-suppliers] .tbl-toolbar .f-input{width:100%}
[data-td-suppliers] .tdsup-contact{display:flex;flex-direction:column;gap:3px;font-size:12px;overflow-wrap:anywhere}
.tdsup-name{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.tdsup-targets{border:0;padding:0;min-width:0}
.tdsup-choice{display:flex;align-items:flex-start;gap:9px;padding:10px 0;min-height:44px;cursor:pointer}
.tdsup-choice input{margin-top:3px;flex-shrink:0}
.tdsup-sheet{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.tdsup-customer,.tdsup-case{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 0;overflow-wrap:anywhere}
.tdsup-customer+.tdsup-customer,.tdsup-case+.tdsup-case{border-top:1px solid var(--border-2)}
.tdsup-case{color:var(--ink);text-decoration:none;min-height:48px}
.tdsup-case:hover{text-decoration:underline}
@media(max-width:900px){[data-td-suppliers] .trow,[data-td-suppliers] .trow-h{grid-template-columns:minmax(120px,1fr) minmax(140px,1.2fr) 1fr 65px minmax(130px,1fr)}}
@media(max-width:640px){
  [data-td-suppliers] .trow{display:flex;flex-direction:column;align-items:stretch;gap:10px}
  [data-td-suppliers] .trow-h{display:none}
  [data-td-suppliers] .trow>[data-k]{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}
  [data-td-suppliers] .trow>[data-k]::before{content:attr(data-k);font-weight:600;min-width:82px;color:var(--text-2)}
  [data-td-suppliers] .trow .tdsup-contact{display:block}
  [data-td-suppliers] .tdsup-contact>*{display:block;margin-top:4px}
  [data-td-suppliers] .cbtn{min-height:44px;margin-top:5px}
  .tdsup-sheet{grid-template-columns:1fr}
  .tdsup-case{flex-wrap:wrap}
}

#dispatchInviteWarning[hidden],#dispatchLinkWarning[hidden]{display:none}
[data-td-suppliers] .trow{padding-top:12px;padding-bottom:12px}
/* The same sent-offer register in all three consoles. Keep the table's
   overflow inside its panel; phones get labelled cards instead. */
.offers-filters{display:flex;align-items:end;gap:12px;flex-wrap:wrap;margin:0 0 22px}
.offers-field{display:flex;flex:1 1 135px;min-width:0;flex-direction:column;gap:6px;font-size:12px;font-weight:600;color:var(--text-2)}
.offers-search{flex:2 1 220px}.offers-field .f-input{width:100%;min-width:0;min-height:40px}
.offers-summary{display:flex;justify-content:space-between;gap:16px;align-items:center;margin-bottom:14px;font-size:13px;flex-wrap:wrap}
.offers-summary>div{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.offers-summary span,.offers-summary small{color:var(--text-3);font-weight:400}
.offers-table-wrap{overflow-x:auto;padding:0}.offers-table{border-collapse:collapse;width:100%;font-size:12px;line-height:1.5;min-width:960px}
.offers-table th{text-align:left;padding:12px 10px;color:var(--text-3);font-size:11px;font-weight:600;background:var(--bg)}
.offers-table td{padding:15px 10px;border-top:1px solid var(--border);vertical-align:top;overflow-wrap:anywhere}
.offers-table td:first-child{white-space:nowrap;min-width:96px}.offers-table td:nth-child(2){min-width:155px;max-width:235px}.offers-table td:nth-child(3),.offers-table td:nth-child(4),.offers-table td:nth-child(6){max-width:125px}
.offers-table td:last-child{min-width:140px}.offers-table .chip{white-space:normal;line-height:1.4}
.offers-table tr:hover{background:var(--bg)}.offers-table td>div{margin-top:4px;color:var(--text-2)}
.offers-ref{color:var(--link);font-weight:650;text-decoration:underline;text-underline-offset:3px;display:inline-flex;align-items:center;min-height:28px}
.offers-money{white-space:nowrap;text-align:right}.offers-money small{display:block;color:var(--text-3);font-size:11px}
.offers-case-state .chip{font-size:10px}.offers-cards{display:none}.offers-pager{display:flex;justify-content:center;align-items:center;gap:14px;margin:22px 0;font-size:13px;color:var(--text-2)}
.offers-empty{padding:28px}.offers-empty h2,.offers-history h2{font-size:16px;margin:0 0 12px}.offers-empty p{color:var(--text-2);line-height:1.65;max-width:640px}
.offers-detail{max-width:850px}.offers-detail-meta{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin:0 0 22px;color:var(--text-2);font-size:13px}
.offers-history{padding:22px;margin-top:22px}.offers-history ol{list-style:none;padding:0;margin:0}.offers-history li{padding:18px 0;border-top:1px solid var(--border)}
.offers-history-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}.offers-history a{color:var(--link);font-weight:600}
.offers-history p{font-size:13px;color:var(--text-2);line-height:1.65;margin:8px 0 0;overflow-wrap:anywhere}.offers-words{white-space:pre-wrap}
@media(max-width:900px){
 .offers-table-wrap{display:none}.offers-cards{display:grid;gap:14px}.offers-card{padding:18px}.offers-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
 .offers-card .offers-ref{min-height:44px}.offers-card h2{font-size:16px;line-height:1.4;margin:10px 0 6px}.offers-card p{font-size:13px;color:var(--text-2);margin:0;line-height:1.6}
 .offers-card-price{display:flex;align-items:baseline;gap:8px;margin:18px 0}.offers-card-price b{font-size:21px}.offers-card-price span{color:var(--text-3);font-size:12px}
 .offers-card dl{margin:0;font-size:12px}.offers-card dl>div{display:flex;align-items:start;justify-content:space-between;gap:12px;padding:9px 0;border-top:1px solid var(--border)}
 .offers-card dt{color:var(--text-3);flex-shrink:0}.offers-card dd{margin:0;text-align:right;overflow-wrap:anywhere}.offers-card dd .chip{white-space:normal;text-align:left}
 .offers-filters{gap:12px}.offers-field{flex-basis:calc(50% - 12px)}.offers-search{flex-basis:100%}.offers-filters .btn{min-height:44px}
 .offers-detail .offer-h{flex-wrap:wrap}.offers-detail .offer-h>div{min-width:0}.offers-detail .oact{flex-wrap:wrap}.offers-detail .oact .btn{min-height:44px}
 .offers-summary>div{gap:8px}.offers-history{padding:18px}.offers-view .page-head{gap:14px;flex-wrap:wrap}
}
/* TD-ATT · the same draft tray on a case, a report and completion photos. */
.attachment-picker{min-width:0;margin-top:8px}
.attachment-picker.is-composer>.filepick{display:none}
.attachment-rows{display:grid;gap:8px}
.attachment-row{display:grid;grid-template-columns:minmax(0,1fr) 36px;gap:6px;align-items:center;padding:8px;border:1px solid var(--border-2);border-radius:10px;background:var(--card);min-width:0}
.attachment-open{display:flex;gap:10px;align-items:center;min-width:0;width:100%;border:0;background:none;color:var(--ink);text-align:left;font:inherit;padding:0;cursor:pointer}
.attachment-thumb{display:grid;place-items:center;flex:0 0 52px;height:52px;border-radius:7px;background:var(--bg);color:var(--text-3);font-size:16px;font-weight:650;overflow:hidden}
.attachment-thumb img{width:100%;height:100%;object-fit:cover}
.attachment-meta{display:grid;min-width:0;gap:4px;font-size:12px;color:var(--text-3)}
.attachment-meta b{font-size:13px;font-weight:600;color:var(--ink);overflow-wrap:anywhere;line-height:1.4}
.attachment-remove.cbtn{width:36px;height:36px;font-size:23px}
.attachment-error,.attachment-progress{grid-column:1/-1;min-width:0}
.attachment-error{font-size:12px;line-height:1.5;color:var(--red,#b42318);overflow-wrap:anywhere}
.attachment-error .btn{margin:5px 0 0}
.attachment-progress:empty{display:none}
.attachment-row.has-error{border-color:var(--red,#b42318)}
.attachment-hint{margin:8px 0;line-height:1.6;overflow-wrap:anywhere}
.attachment-open:focus-visible,.attachment-remove:focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.attachment-preview{box-sizing:border-box;width:min(960px,calc(100vw - 24px));max-height:calc(100dvh - 32px);padding:18px;border:1px solid var(--border-2);border-radius:14px;background:var(--card);color:var(--ink)}
.attachment-preview::backdrop{background:rgba(0,0,0,.65)}
.attachment-preview-head{display:flex;gap:12px;align-items:center;justify-content:space-between;margin-bottom:14px}
.attachment-preview-head b{min-width:0;overflow-wrap:anywhere}
.attachment-preview-head .btn{flex-shrink:0}
.attachment-preview-body{display:grid;place-items:center;min-height:80px}
.attachment-preview-body img,.attachment-preview-body video{display:block;max-width:100%;max-height:68dvh;object-fit:contain}
.attachment-preview>.hint{margin-top:12px;overflow-wrap:anywhere}
.message-files{margin-top:8px;display:grid;gap:8px;min-width:0}
.message-files .fileline{margin:0}
@media(max-width:640px){.attachment-preview{padding:12px}.attachment-row{padding:7px}.attachment-thumb{flex-basis:44px;height:44px}.attachment-remove.cbtn{min-height:44px}.attachment-hint{font-size:12px}}
