
@font-face{font-family:'Inter';font-style:normal;font-display:swap;font-weight:100 900;
  src:url('/fonts/Inter-latin.woff2') 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-display:swap;font-weight:100 900;
  src:url('/fonts/Inter-latin-ext.woff2') 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:'JetBrains Mono';font-style:normal;font-display:swap;font-weight:400 600;
  src:url('/fonts/JetBrainsMono-latin.woff2') 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}

/* ── tokens ─────────────────────────────────────────────────────────────────
   Names are kept from the previous system so every page keeps working; the
   VALUES are the DESIGN.md palette. --bg is the canvas, --surface the card,
   --surface-2 the muted strip inside a card, --rail the sidebar ground. */
:root{
  --bg:#f4f5f8;
  --surface:#fff;
  --surface-solid:#fff;
  --surface-2:#f8fafc;
  --surface-3:#f2f5f8;
  --rail:#ffffff;
  --rail-2:#e5e9f0;
  --line:#ececf0;
  --line-strong:#dbdde3;
  --line-soft:#ececec;

  --raise:#fff;
  --raise-hover:#f8fafc;
  --raise-solid:#fff;
  --dot:rgba(3,7,18,.06);
  --scrim:rgba(17,27,41,.46);

  --ink:#0b0e15;
  --ink-2:#0b1018;
  --ink-3:#4a5567;
  /* #727378 cleared 4.5:1 on WHITE (4.73) but not on the surfaces this step
     actually appears on: 4.34 on the app ground and 4.32 on --surface-3, so
     the period chips, the tab strip and every page subtitle sat under the
     threshold. Contrast is a property of the pair, not of the ink, and the
     faint step is used on all four backgrounds. 4.86 worst case now. */
  --ink-4:#646771;
  --ink-5:#76757a;
  --on-rail:#030712;
  --on-rail-dim:#4a5567;

  /* One accent. --accent and --blue are the SAME hue on purpose: the old
     system split "action" and "navigation" across coral and blue; this one
     has a single primary and lets weight and placement do the rest. */
  --accent:#275ffc;
  --accent-hover:#1c4fe0;
  --accent-soft:#f0f4ff;
  --accent-line:#bcd6ff;
  --accent-ink:#2b5df3;
  --blue:#275ffc;
  --link:#275ffc;
  --link-hover:#1c4fe0;
  --blue-soft:#e8f1ff;
  --blue-line:#bcd6ff;

  /* Semantic pairs: soft background + saturated text, never a border. */
  --ok:#43c472;   --ok-soft:#eefcf3;   --ok-line:#bdf5e1;
  --warn:#c98f00; --warn-soft:#ffefcc; --warn-line:#ffe2a3;
  --bad:#d14477;  --bad-soft:#fdeef4;  --bad-line:#ffd5d8;
  --info:#3963f8; --info-soft:#e3eafe; --info-line:#c7d5fd;
  /* A FOURTH member of each semantic set: the ink used when the colour has to
     carry TEXT on its own soft background. The base hues are tuned for fills,
     strokes and chart series, where 3:1 against the page is plenty — as text
     on their -soft they measured ok 2.12, warn 2.49, bad 3.89, info 4.05, so
     every status badge in the portal sat under 4.5:1. Darkening the base
     tokens instead would have dragged the charts and the VAT gauge with them,
     so the ink is its own step and the graphics keep their colour. */
  --ok-ink:#157f45;
  --warn-ink:#7a5600;
  --bad-ink:#a8265a;
  --info-ink:#2c4fd0;
  /* Money lost, and only that. --bad-ink is the portal's pink-red for delete
     buttons and error text — right for "careful", too soft for a figure that
     should land as a loss the moment the page paints. Kept separate so
     hardening the red here never makes every delete icon shout.
     Blood red, 6.22:1 on white and 5.71:1 on the app ground. */
  --loss:#c1121f;
  /* Profit. A brighter green fails on the grey ground (#0f8a4a is 4.05 there),
     so this is the most vivid one that still clears 4.5 on all four surfaces. */
  --gain:#0b7a40;
  --purple:#6b39f8; --purple-soft:#ebe4fe;
  --pink:#f83995;  --pink-soft:#fce2ef;
  --teal:#0fa97c;  --teal-soft:#bdf5e1;

  /* Depth is tonal. These exist only for floating layers (menus, dialogs). */
  --shadow-sm:0 1px 3px rgba(16,24,40,.06),0 1px 2px rgba(16,24,40,.04);
  --shadow:0 8px 24px rgba(16,24,40,.08),0 1px 2px rgba(16,24,40,.04);
  --shadow-lg:0 24px 60px rgba(16,24,40,.16),0 2px 6px rgba(16,24,40,.06);

  --chart-line:#2d5bf0;
  --chart-line-soft:#bcd6ff;
  --chart-2:#3dc2ec;
  /* ── The financial colour system ──────────────────────────────────────
     ONE meaning per hue, used by every surface that shows money: the KPI
     tiles, the chart series, its legend, the category bars and the VAT card.
     Anything that reads a figure reads these tokens, so a colour cannot mean
     "income" in one card and something else two cards over.

       --fin-income   green   money arriving        (Recettes)
       --fin-expense  orange  money leaving         (Dépenses, category bars)
       --fin-vat      amber   a balance to settle   (TVA — neither good nor bad)
       --gain/--loss  green/red  the RESULT, by sign

     Note green appears twice on purpose: Recettes is money in, and a profit
     is money left over — the same direction. --gain is a step darker so the
     two are distinguishable where they sit side by side in the legend.
     Blue is deliberately NOT in this list: it stays interface chrome (the
     accent, links, active states) so it never reads as a financial value. */
  --fin-income:#157f45;
  --fin-expense:#f07a2e;
  --fin-vat:#eaaa42;
  /* Softs, for bar tracks and tinted chips built from the same set. */
  --fin-income-soft:#e8f6ee;
  --fin-expense-soft:#fdefe4;
  --fin-vat-soft:#fdf3e0;

  --chart-expense:var(--fin-expense);
  --chart-net:#2d5bf0;
  /* The same series, dark enough to be read as text. See .chart-lede-n. */
  --chart-net-ink:#1c3fa8;
  --chart-vat:var(--fin-vat);
  --chart-muted:#9ca3af;
  --chart-grid:#eef1f5;
  /* Axis ticks sit one notch off the muted ink — dark enough to read at 12px,
     light enough that the numbers never compete with the line they label. */
  /* Was #76757a — 4.3:1, under the bar, on the smallest text in the interface
     (12px date ticks). Matched to --ink-4 so the axis reads as the same rank of
     secondary text as every other hint on the page. */
  --chart-axis:#646771;
  /* The dashed rules behind the plot. Its own token, NOT --chart-grid: that
     one also backs solid UI edges elsewhere and is far too dark here. The
     reference's grid reads as a suggestion of a line, so this is nearly the
     card colour — visible enough to carry the eye across to a tick, never
     enough to be seen as part of the drawing. */
  --chart-gridline:#f1f3f7;
  /* The dashed comparison series. Grey by rule, not by omission. */
  --chart-compare:#c9cacf;
  /* Stops of the area gradient under the live series. A near-white wash, as
     sampled: the fill is there to give the line a body, not to be a block of
     colour competing with it. */
  --chart-area-top:#e2e9ff;
  --chart-area-bottom:#f9faff;
  /* Gauge ticks: green is the resting fill, the track is the unfilled rest. */
  /* The track behind a horizontal bar. */
  --chart-track:#eef1f5;
  --flag:#eac03c;
  --code-ink:#d7dcea;
  --code-bg:#161729;
  --notice-bg:#fff8e1;

  --r-xs:4px; --r-sm:6px; --r:8px; --r-md:12px; --r-lg:16px; --r-xl:20px; --pill:9999px;
  --ease:cubic-bezier(.23,1,.32,1);
  --side-w:240px;

  /* ── type scale ───────────────────────────────────────────────────────
     One ladder, so a size is chosen by RANK rather than by taste at the
     point of use. --fs-body is the floor: 14px on a pointer, 15px on a
     phone (see the 640px block), which is the smallest comfortable reading
     size on a device held at arm's length.

       caption  labels, tab bar, table meta
       small    secondary text, hints
       body     the default
       lead     row titles — the thing you scan a list for
       title    page h1
       display  stat figures */
  --fs-caption:11.5px;
  --fs-small:13px;
  --fs-body:14px;
  --fs-lead:16px;
  --fs-title:24px;
  --fs-display:28px;

  /* The phone tab bar. Its ground is opaque under a blur so a list scrolling
     beneath it never shows through as legible text. --tab-ink is --ink-4
     (5.44:1 on white); the active tab takes the accent (5.32:1). */
  --tabbar:rgba(255,255,255,.86);
  --tabbar-line:var(--line);
  --tab-ink:var(--ink-4);
  --tab-on:var(--accent);
  /* Clearance the scroll container leaves for the bar: its height plus the
     home-indicator inset plus breathing room.
     Measured, not guessed: 4px + 4px padding around a 22px glyph over its
     label comes to 61px. The old 56px understated the bar by 5px, which came
     straight out of the gap at the end of a list. */
  --tabbar-h:62px;
  color-scheme:light;
}

/* ── dark ───────────────────────────────────────────────────────────────────
   The same tokens re-pointed to a cool navy family (the Investment cover is
   the reference). Surfaces get lighter as they come forward; the primary is
   lifted so it clears 4.5:1 on the dark ground. Written twice — once under
   the OS preference for 'auto', once unconditionally for 'dark'. */
@media (prefers-color-scheme:dark){
  [data-theme='auto']{
    --ok-ink:#6ee7b7;--warn-ink:#fcd34d;--bad-ink:#fda4af;
    --bg:#0b0f1a;--surface:#121826;--surface-solid:#121826;--surface-2:#182033;--surface-3:#1c2538;
    --rail:#121826;--rail-2:#1e2739;--line:#1f2937;--line-strong:#2a3549;--line-soft:#1a2232;
    --raise:#182033;--raise-hover:#1f2a40;--raise-solid:#182033;--dot:rgba(230,233,240,.07);--scrim:rgba(2,6,16,.7);
    --ink:#eef1f6;--ink-2:#dfe4ec;--ink-3:#aab3c2;--ink-4:#8b95a7;--ink-5:#5f6b80;--on-rail:#eef1f6;--on-rail-dim:#aab3c2;
    --accent:#4d8dff;--accent-hover:#6ea1ff;--accent-soft:rgba(77,141,255,.16);--accent-line:rgba(77,141,255,.4);--accent-ink:#bcd6ff;
    --blue:#4d8dff;--link:#6ea1ff;--link-hover:#9dbfff;--blue-soft:rgba(77,141,255,.16);--blue-line:rgba(77,141,255,.4);
    --ok:#34d399;--ok-soft:rgba(52,211,153,.14);--ok-line:rgba(52,211,153,.35);
    --warn:#fbbf24;--warn-soft:rgba(251,191,36,.14);--warn-line:rgba(251,191,36,.35);
    --bad:#fb7185;--bad-soft:rgba(251,113,133,.14);--bad-line:rgba(251,113,133,.35);
    --info:#7c9cff;--info-soft:rgba(124,156,255,.16);--info-line:rgba(124,156,255,.4);
    --purple:#a78bfa;--purple-soft:rgba(167,139,250,.16);--pink:#f472b6;--pink-soft:rgba(244,114,182,.16);--teal:#2dd4bf;--teal-soft:rgba(45,212,191,.16);--teal-ink:#5eead4;
    --chart-line:#4d8dff;--chart-line-soft:#274a86;--chart-2:#3dc2ec;--fin-income:#34d399;--fin-expense:#ff9d5c;--fin-vat:#e0a33c;--fin-income-soft:rgba(52,211,153,.14);--fin-expense-soft:rgba(255,157,92,.14);--fin-vat-soft:rgba(224,163,60,.14);--chart-expense:#ff9d5c;--loss:#ff6b6b;--gain:#34d399;--chart-net:#7aa2ff;--chart-net-ink:#a8c4ff;--chart-vat:#e0a33c;--chart-muted:#5f6b80;--chart-grid:#1f2937;--chart-axis:#8b95a7;--chart-gridline:#1a2232;--chart-compare:#4b5568;--chart-area-top:rgba(77,141,255,.15);--chart-area-bottom:rgba(77,141,255,0);--chart-track:#1f2937;--flag:#fbbf24;--notice-bg:rgba(251,191,36,.14);
    --shadow-sm:0 1px 2px rgba(0,0,0,.3);--shadow:0 8px 24px rgba(0,0,0,.45),0 1px 2px rgba(0,0,0,.3);--shadow-lg:0 24px 60px rgba(0,0,0,.6),0 2px 6px rgba(0,0,0,.4);
    --tabbar:rgba(18,24,38,.88);--tabbar-line:var(--line-strong);--tab-ink:var(--ink-4);--tab-on:var(--accent);
    color-scheme:dark;
  }
}
[data-theme='dark']{
  --ok-ink:#6ee7b7;--warn-ink:#fcd34d;--bad-ink:#fda4af;
  --bg:#0b0f1a;--surface:#121826;--surface-solid:#121826;--surface-2:#182033;--surface-3:#1c2538;
  --rail:#0e1320;--rail-2:#1e2739;--line:#1f2937;--line-strong:#2a3549;--line-soft:#1a2232;
  --raise:#182033;--raise-hover:#1f2a40;--raise-solid:#182033;--dot:rgba(230,233,240,.07);--scrim:rgba(2,6,16,.7);
  --ink:#eef1f6;--ink-2:#dfe4ec;--ink-3:#aab3c2;--ink-4:#8b95a7;--ink-5:#5f6b80;--on-rail:#eef1f6;--on-rail-dim:#aab3c2;
  --accent:#4d8dff;--accent-hover:#6ea1ff;--accent-soft:rgba(77,141,255,.16);--accent-line:rgba(77,141,255,.4);--accent-ink:#bcd6ff;
  --blue:#4d8dff;--link:#6ea1ff;--link-hover:#9dbfff;--blue-soft:rgba(77,141,255,.16);--blue-line:rgba(77,141,255,.4);
  --ok:#34d399;--ok-soft:rgba(52,211,153,.14);--ok-line:rgba(52,211,153,.35);
  --warn:#fbbf24;--warn-soft:rgba(251,191,36,.14);--warn-line:rgba(251,191,36,.35);
  --bad:#fb7185;--bad-soft:rgba(251,113,133,.14);--bad-line:rgba(251,113,133,.35);
  --info:#7c9cff;--info-soft:rgba(124,156,255,.16);--info-line:rgba(124,156,255,.4);
  --purple:#a78bfa;--purple-soft:rgba(167,139,250,.16);--pink:#f472b6;--pink-soft:rgba(244,114,182,.16);--teal:#2dd4bf;--teal-soft:rgba(45,212,191,.16);--teal-ink:#5eead4;
  --chart-line:#4d8dff;--chart-line-soft:#274a86;--chart-2:#3dc2ec;--fin-income:#34d399;--fin-expense:#ff9d5c;--fin-vat:#e0a33c;--fin-income-soft:rgba(52,211,153,.14);--fin-expense-soft:rgba(255,157,92,.14);--fin-vat-soft:rgba(224,163,60,.14);--chart-expense:#ff9d5c;--loss:#ff6b6b;--gain:#34d399;--chart-net:#7aa2ff;--chart-net-ink:#a8c4ff;--chart-vat:#e0a33c;--chart-muted:#5f6b80;--chart-grid:#1f2937;--chart-axis:#8b95a7;--chart-gridline:#1a2232;--chart-compare:#4b5568;--chart-area-top:rgba(77,141,255,.15);--chart-area-bottom:rgba(77,141,255,0);--chart-track:#1f2937;--flag:#fbbf24;--notice-bg:rgba(251,191,36,.14);
  --shadow-sm:0 1px 2px rgba(0,0,0,.3);--shadow:0 8px 24px rgba(0,0,0,.45),0 1px 2px rgba(0,0,0,.3);--shadow-lg:0 24px 60px rgba(0,0,0,.6),0 2px 6px rgba(0,0,0,.4);
    --tabbar:rgba(18,24,38,.88);--tabbar-line:var(--line-strong);--tab-ink:var(--ink-4);--tab-on:var(--accent);
  color-scheme:dark;
}

/* The KRUZ wordmark is one flat navy; invert it on a dark ground. */
[data-theme='dark'] .auth-home img,
[data-theme='dark'] .auth-brand img{filter:brightness(0) invert(1);opacity:.92}
@media (prefers-color-scheme:dark){
  [data-theme='auto'] .auth-home img,
  [data-theme='auto'] .auth-brand img{filter:brightness(0) invert(1);opacity:.92}
}

/* ── base ──────────────────────────────────────────────────────────────── */
*{box-sizing:border-box}
/* Reserve the scrollbar's width on every page, scrolling or not. Without it a
   short page (no scrollbar) is a dozen pixels wider than a long one, and the
   centred .work slides sideways as you move between routes. */
html{-webkit-text-size-adjust:100%;scrollbar-gutter:stable}
body{margin:0;background:var(--bg);color:var(--ink-2);
  font-family:'Inter',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  font-size:var(--fs-body);line-height:1.5;min-height:100dvh;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  font-feature-settings:'cv11','ss01'}

::selection{background:var(--accent-soft);color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
*{scrollbar-width:thin;scrollbar-color:var(--line-strong) transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:99px;
  border:3px solid transparent;background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:var(--ink-5);background-clip:content-box}
*::-webkit-scrollbar-track{background:transparent}

/* Type: one family, weight and tracking carry the hierarchy. */
h1,h2,h3{color:var(--ink);font-family:inherit;font-weight:600;margin:0;text-wrap:balance}
h1{font-size:22px;line-height:1.25;letter-spacing:-.02em}
h2{font-size:15px;line-height:1.35;letter-spacing:-.01em}
h3{font-size:14px;line-height:1.4;letter-spacing:-.005em}
p{margin:0}
a{color:var(--link);text-decoration:none;font-weight:500}
a:hover{color:var(--link-hover);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px}

.mono,.money,.pct,.dt,.lead-date{font-family:inherit;font-variant-numeric:tabular-nums;
  letter-spacing:-.005em}
.sub{color:var(--ink-4);font-size:13px}
.muted{color:var(--ink-4);font-size:12.5px}
.hint{color:var(--ink-4);font-size:12.5px;line-height:1.55;margin:8px 0 0}
.eyebrow{font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-4);margin:0 0 6px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

/* Inline help — the small "?" beside a label.
   ---------------------------------------------------------------------------
   CSS only, because the portal ships no JavaScript: the bubble is a sibling
   span revealed on hover and on :focus-visible. A <button> rather than a bare
   span so it is reachable by keyboard and announced; type="button" so it never
   submits the form it sits in. aria-describedby ties it to the bubble, which
   is what a screen reader reads instead of the hover.
   The bubble is positioned by a wrapper with position:relative and is
   pointer-events:none, so it can never swallow a click meant for the input. */
/* flex:none on BOTH the wrapper and the button, and the sizes repeated as
   min-/max-: a label is a flex container here, so the 15px width was treated
   as a starting basis and stretched — border-radius:50% on a stretched box
   draws an ellipse, not a circle. Locking all three axes is what keeps it
   round wherever it is dropped. */
.help{position:relative;display:inline-flex;flex:none;vertical-align:middle;margin-left:5px}
.help-b{display:inline-flex;flex:none;align-items:center;justify-content:center;
  box-sizing:border-box;width:15px;height:15px;min-width:15px;max-width:15px;
  min-height:15px;max-height:15px;
  padding:0;border:1px solid var(--line);border-radius:50%;
  background:none;color:var(--ink-4);font-size:10px;font-weight:600;line-height:1;
  cursor:help;transition:color .12s,border-color .12s}
.help-b:hover,.help-b:focus-visible{color:var(--ink-2);border-color:var(--ink-4)}
/* --ink-2 is the darkest ink this palette actually defines; --ink-1 does not
   exist, and naming it gave the bubble no background at all — white text on
   the card, unreadable. #fff rather than --bg for the same reason: --bg is the
   page grey, which has too little contrast against --ink-2. */
.help-t{position:absolute;bottom:calc(100% + 7px);left:50%;transform:translateX(-50%);
  z-index:40;width:max-content;max-width:250px;padding:7px 9px;border-radius:7px;
  background:var(--ink-2);color:#fff;font-size:11.5px;font-weight:400;
  line-height:1.45;letter-spacing:0;text-align:left;text-transform:none;
  white-space:normal;opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .12s,visibility .12s;box-shadow:0 6px 20px rgba(0,0,0,.18)}
.help-t::after{content:"";position:absolute;top:100%;left:50%;margin-left:-4px;
  border:4px solid transparent;border-top-color:var(--ink-2)}
.help-b:hover+.help-t,.help-b:focus-visible+.help-t{opacity:1;visibility:visible}
/* Near the right edge the bubble would overflow the card; these flip it. */
.help.help-end .help-t{left:auto;right:0;transform:none}
.help.help-end .help-t::after{left:auto;right:5px;margin-left:0}
@media (prefers-reduced-motion:reduce){.help-b,.help-t{transition:none}}

/* ── shell ──────────────────────────────────────────────────────────────────
   A fixed full-height sidebar on the rail tint with a right hairline, and a
   canvas beside it. The sidebar never moves between routes. */
.shell{min-height:100dvh;position:relative;isolation:isolate}

.skip{position:absolute;left:-9999px;top:8px;z-index:200;padding:8px 14px;border-radius:var(--r);
  background:var(--ink);color:#fff;font-size:13px;font-weight:600}
.skip:focus{left:16px;text-decoration:none;color:#fff}

.side{position:fixed;top:0;left:0;bottom:0;width:var(--side-w);z-index:60;
  display:flex;flex-direction:column;gap:0;padding:16px 16px 14px;
  background:var(--rail);border-right:1px solid var(--line);overflow-y:auto}
.side-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:14px}
.side-brand{display:flex;align-items:center;color:var(--ink)}
.side-brand:hover{text-decoration:none}

/* Workspace card: the first thing in the rail, as in the reference. */
.side-ws{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:12px;
  padding:12px;min-height:64px;border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--surface);color:var(--ink);text-decoration:none}
.side-ws:hover{text-decoration:none;border-color:var(--line-strong);color:var(--ink)}
.side-ws .av,.side-user .av,.topnav-ws .av{width:40px;height:40px;border-radius:var(--r-md);flex:0 0 auto;
  display:grid;place-items:center;background:hsl(var(--av-h,222) 62% 46%);color:#fff;
  font-size:11.5px;font-weight:600;letter-spacing:.02em}
.side-ws-copy{min-width:0;display:flex;flex-direction:column;line-height:1.25;gap:1px}
.side-ws .nm{font-size:14px;font-weight:600;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-ws .rl{font-size:11.5px;color:var(--ink-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-ws-chev{margin-left:auto;color:var(--ink-5);flex:0 0 auto;display:grid}
.side-ws-chev svg{width:16px;height:16px}
.topnav-ws .av{width:32px;height:32px;border-radius:var(--r)}

.side-label{margin:16px 12px 6px;font-size:11px;font-weight:500;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-4)}
.side-nav{display:flex;flex-direction:column;gap:2px}
.side-nav a{height:36px;display:flex;align-items:center;gap:10px;padding:0 12px;
  border-radius:var(--r);color:var(--ink-3);font-size:14px;font-weight:500;text-decoration:none;
  transition:background .15s var(--ease),color .15s var(--ease)}
.side-nav a:hover{background:var(--surface);color:var(--ink);text-decoration:none}
/* Active: a white pill with dark text and a hairline — "you are here" is a
   statement, not an action, so it takes no colour. The icon alone turns blue. */
.side-nav a[aria-current='page']{background:var(--surface);color:var(--ink);font-weight:600;
  box-shadow:0 0 0 1px var(--line-strong),0 1px 2px rgba(16,24,40,.06)}
.side-nav a[aria-current='page'] svg{color:var(--ink)}
.side-nav svg{width:18px;height:18px;flex:0 0 auto;color:var(--ink-4)}

.side-foot{margin-top:auto;padding-top:8px;border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:2px}
.side-tools{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 4px;min-height:36px}
.side .lang-dd summary{border-color:transparent;background:transparent;padding:0 8px 0 4px;min-height:32px;color:var(--ink-3)}
.side .lang-dd summary:hover,.side .lang-dd[open] summary{background:var(--surface);color:var(--ink)}
.side .theme-switch{border-color:transparent;background:transparent;padding:0;gap:0}
.side .theme-opt{width:30px;min-height:30px;color:var(--ink-3);opacity:.9}
.side .theme-opt.is-active{background:var(--surface);box-shadow:0 0 0 1px var(--line)}
.side-user{display:flex;align-items:center;gap:10px;min-width:0;padding:6px 8px;border-radius:var(--r)}
.side-user-copy{min-width:0;display:flex;flex-direction:column;line-height:1.25}
.side-user .nm{font-size:13px;color:var(--ink);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-user .rl{font-size:11.5px;color:var(--ink-4)}
.side-signout{width:100%;min-height:36px;margin:0;padding:0 12px;display:flex;align-items:center;gap:10px;
  background:transparent;border:0;color:var(--ink-3);
  font-size:14px;font-weight:500;border-radius:var(--r);
  transition:background .15s var(--ease),color .15s var(--ease)}
.side-signout svg{width:18px;height:18px;margin:0;flex:0 0 auto;color:var(--ink-4)}
.side-signout:hover{background:var(--surface);color:var(--ink)}
.side-signout:hover svg{color:var(--bad)}

.nav-toggle{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;appearance:none}
.nav-scrim,.nav-open,.nav-close{display:none}
.topnav{display:none}

/* ── phone tab bar ──────────────────────────────────────────────────────
   Hidden entirely on a pointer, where the rail is already permanent and
   better. It only becomes navigation below 920px (see the responsive
   block); everything here is the look, not the switch. */
.tabbar{display:none}
.tabbar a,.tabbar-more{
  flex:1 1 0;min-width:0;
  /* 44px is the floor; the bar gives each target the full height of the
     bar and an equal share of its width, so there is no gap between two
     tabs that lands on nothing. Height is FIXED rather than a minimum:
     the tabs are one row of equals, and letting them size to content made
     the five disagree whenever one label was a pixel taller. */
  height:52px;min-height:52px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  padding:6px 2px 4px;border-radius:var(--r);
  color:var(--tab-ink);font-size:11px;font-weight:600;line-height:1.1;
  text-decoration:none;cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:color .15s var(--ease)}
.tabbar a span,.tabbar-more span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The More tab is a <label> for the drawer toggle: undo the form-label rule
   (block, 13px, top margin) that otherwise pushes it below its neighbours. */
.tabbar-more{margin:0;font-size:11px;font-weight:600;color:var(--tab-ink)}
.tabbar svg{width:22px;height:22px;flex:0 0 auto;color:currentColor;
  transition:transform .18s var(--ease)}
.tabbar a:hover,.tabbar-more:hover{color:var(--ink-2);text-decoration:none}
/* Current section: the icon and the label both take the accent. Colour is
   not the only carrier — the label goes to 700 and the icon lifts 1px, so
   the state survives a colour-blind reader and a greyscale screenshot. */
.tabbar a[aria-current='page']{color:var(--tab-on);font-weight:700}
.tabbar a[aria-current='page'] svg{transform:translateY(-1px)}
.tabbar a:focus-visible,.tabbar-more:focus-visible{outline:2px solid var(--accent);outline-offset:-3px}

/* The signature: the fifth tab wears the workspace avatar rather than an
   ellipsis, so the account's own colour is permanently in the navigation
   and switching workspace visibly recolours it. */
/* Self-contained: the avatar's fill lives on a compound selector listing
   the three places it appeared before, so a bare .av inherits nothing. */
.tabbar-av{width:22px;height:22px;border-radius:7px;flex:0 0 auto;
  display:grid;place-items:center;background:hsl(var(--av-h,222) 62% 46%);color:#fff;
  font-size:9px;font-weight:700;letter-spacing:0;line-height:1}
.tabbar-more[data-on='1']{color:var(--ink-2)}
.tabbar-more[data-on='1'] .tabbar-av{box-shadow:0 0 0 2px var(--surface),0 0 0 3.5px var(--tab-on)}
.nav-toggle:checked~.tabbar .tabbar-more{color:var(--tab-on)}
@media (prefers-reduced-motion:reduce){
  .tabbar a,.tabbar-more,.tabbar svg{transition:none}
  .tabbar a[aria-current='page'] svg{transform:none}
}

.canvas{margin-left:var(--side-w);min-width:0}
.work{position:relative;z-index:1;width:min(1240px,100%);min-width:0;margin:0 auto;
  padding:24px 24px 64px}
/* The header is the page's anchor: the title sits in the same spot on every
   route, and what follows starts at the same y. So the block is a fixed height
   — tall enough for a title, one line of subtitle and a 40px action button —
   with the copy pinned to the top rather than centred against the actions. */
.topbar{position:relative;display:flex;justify-content:space-between;align-items:flex-start;gap:20px;
  height:56px;margin-bottom:20px;padding:0}
.topbar-copy{min-width:0;max-width:720px}
.topbar h1{margin-bottom:0}
.topbar .eyebrow{display:none}
/* One line, clipped: a long subtitle must not push the page down a row. */
.topbar .sub{max-width:620px;font-size:13px;line-height:24px;color:var(--ink-4);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar .actions{align-self:center}
.topbar .actions{display:flex;gap:8px;align-items:center;flex-shrink:0}

/* ── cards ──────────────────────────────────────────────────────────────── */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:20px;margin-bottom:16px;box-shadow:var(--shadow-sm)}
.card h2{margin-bottom:12px}
h2 > svg{width:16px;height:16px;flex:0 0 auto;color:var(--ink-4);vertical-align:-3px;margin-right:8px}
.card h2{display:flex;align-items:center;gap:0}
.card h2 > svg{margin-right:8px;vertical-align:0}
.card-hd{display:flex;justify-content:space-between;align-items:center;gap:12px;
  flex-wrap:wrap;margin-bottom:14px}
.card-hd h2{margin:0}
.card-hd>a{font-size:13px;font-weight:500;color:var(--ink-3)}
.card-hd>a:hover{color:var(--ink)}

/* Icon tile: a 32px square, white with a hairline, that prefixes a card title
   or a list row. Tinted variants exist for state. */
.itile{width:32px;height:32px;border-radius:var(--r);display:grid;place-items:center;flex:0 0 auto;
  background:var(--surface);border:1px solid var(--line);color:var(--ink-4)}
.itile.is-accent{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.itile svg{width:16px;height:16px}

.workspace-card{display:grid;grid-template-columns:minmax(210px,.72fr) minmax(340px,1.28fr);
  align-items:center;gap:18px 28px;padding:20px}
.workspace-card-copy{display:flex;align-items:center;gap:13px}
.workspace-card-copy .eyebrow{margin-bottom:4px}
.workspace-card-copy h2{margin:0;font-size:18px}
.workspace-icon,.status-icon{width:40px;height:40px;display:grid;place-items:center;flex:0 0 auto;
  border-radius:var(--r-md);background:var(--accent-soft);color:var(--accent)}
.workspace-form{align-items:center;flex-wrap:nowrap;gap:8px}
.workspace-form label{margin:0}
.workspace-form .narrow{flex-basis:128px;min-width:128px}
.workspace-form button{width:100%}
.workspace-hint{grid-column:1/-1;margin:0;padding-top:12px;border-top:1px solid var(--line)}

.status-card{display:flex;align-items:center;gap:16px;min-height:0}
.status-copy{min-width:0;flex:1}
.status-copy .card-hd{margin:0 0 4px}
.status-copy .sub{margin:0}
.status-icon{background:var(--surface-3);color:var(--ink-4)}
.status-icon.is-live{background:var(--ok-soft);color:var(--ok)}
.status-icon.is-down{background:var(--bad-soft);color:var(--bad)}
.status-icon svg{width:18px;height:18px}
.status-action{min-height:40px;display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;padding:0 12px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  color:var(--ink);font-size:13px;font-weight:500;text-decoration:none}
.status-action:hover{background:var(--surface-2);color:var(--ink);text-decoration:none}
.status-meta{line-height:1.6}
/* The ticks SHARE the strip's width rather than each taking a fixed 6px, so
   the record spans the card instead of stopping halfway across it. Slots that
   have not been checked yet are drawn faint, which is also what keeps a young
   site from rendering four fat slabs. */
.uptime-strip{display:flex;align-items:flex-end;gap:2px;margin-top:12px;overflow:hidden}
.uptime-bar{flex:1 1 0;min-width:2px;height:22px;border-radius:99px}
.uptime-bar.is-up{background:var(--ok);opacity:.75}
.uptime-bar.is-down{background:var(--bad)}
.uptime-bar.is-pending{background:var(--line);height:14px}
.uptime-caption{margin-top:6px}

/* ── stat tiles ───────────────────────────────────────────────────────────
   Label with an icon tile at the right, the figure with its delta chip, then
   the footnote. Quarter-width on a 16px gutter. */
.stats{display:grid;gap:16px;margin:0 0 16px;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.stats>.stat{min-width:0}
.stat{display:block;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);padding:16px 18px;box-shadow:none;
  color:inherit;text-decoration:none;font-weight:400;
  transition:border-color .15s var(--ease)}
.stat:hover{border-color:var(--line-strong);text-decoration:none;color:inherit}
.stat .l{display:flex;align-items:center;justify-content:space-between;gap:9px;
  font-size:13px;font-weight:500;color:var(--ink-4);margin-bottom:12px}
.stat-icon{width:32px;height:32px;border-radius:var(--r);display:grid;place-items:center;
  flex:0 0 auto;background:var(--surface);border:1px solid var(--line);color:var(--ink-4)}
.stat .l svg{width:16px;height:16px;color:currentColor}
.stat .n{font-family:inherit;font-size:24px;font-weight:600;line-height:1.1;
  color:var(--ink);letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.stat .u{font-size:14px;font-weight:500;color:var(--ink-4);letter-spacing:0}
.stat .d{font-size:12px;font-weight:500;padding:3px 8px;border-radius:99px;
  font-variant-numeric:tabular-nums;letter-spacing:0;align-self:center;line-height:1.3}
.stat .d.up{background:var(--ok-soft);color:var(--ok-ink)}
.stat .d.down{background:var(--bad-soft);color:var(--bad-ink)}
.stat .d.flat{background:var(--surface-3);color:var(--ink-4)}
.stat .f{font-size:12.5px;color:var(--ink-4);margin-top:6px;display:block}
.stat.accent .stat-icon{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.stat.warn .stat-icon{background:var(--bad-soft);border-color:transparent;color:var(--bad)}
.stat.good .stat-icon{background:var(--ok-soft);border-color:transparent;color:var(--ok)}

/* ── compact metric pills ─────────────────────────────────────────────────
   Bare counts in one line: dot or icon, number, word. */
.metrics{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 16px}
.metric{display:inline-flex;align-items:center;gap:7px;padding:0 12px 0 10px;min-height:32px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  font-size:13px;color:var(--ink-3);text-decoration:none;line-height:1;
  transition:border-color .15s var(--ease),background .15s var(--ease)}
a.metric:hover{border-color:var(--line-strong);background:var(--surface-2);
  text-decoration:none;color:var(--ink)}
.metric .n{font-weight:600;font-size:13px;color:var(--ink);font-variant-numeric:tabular-nums}
.metric .dot{width:8px;height:8px;border-radius:99px;flex:0 0 auto;background:var(--ink-5)}
.metric .n .u{font-size:11px;font-weight:500;color:var(--ink-4);margin-left:1px}
.metric.good .dot{background:var(--ok)}
.metric.warn .dot{background:var(--bad)}
.metric.warn .n{color:var(--bad-ink)}
.metric.accent{background:var(--surface);border-color:var(--line);color:var(--ink-3)}
.metric.accent .n{color:var(--ink)}
a.metric.accent:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink)}
.metric svg{width:14px;height:14px;color:var(--ink-4);flex:0 0 auto}
.metric.accent svg{color:var(--ink-3)}
.metric.warn svg{color:var(--bad)}
.metric.good svg{color:var(--ok)}

/* ── controls ───────────────────────────────────────────────────────────── */
label{display:block;font-size:13px;font-weight:500;color:var(--ink-2);margin:14px 0 6px}
input,select,textarea{width:100%;min-height:40px;padding:9px 12px;border-radius:var(--r);
  border:1px solid var(--line);background:var(--surface);color:var(--ink);
  font-size:14px;font-family:inherit;line-height:1.4;
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease)}
input:hover,select:hover,textarea:hover{border-color:var(--line-strong)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft)}
input::placeholder,textarea::placeholder{color:var(--ink-5)}
input:disabled,select:disabled,textarea:disabled{background:var(--surface-2);
  color:var(--ink-4);cursor:not-allowed}
textarea{min-height:88px;resize:vertical}
select{appearance:none;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236b7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 10px center;padding-right:32px}

/* custom select (portal.js) */
.cs{position:relative;width:100%}
.cs:has(.cs-list.is-open){z-index:55}
.card:has(.cs-list.is-open),.crow:has(.cs-list.is-open),
.toolbar:has(.cs-list.is-open){position:relative;z-index:55}
.cs select{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.cs-btn{display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;min-height:40px;padding:9px 12px;border-radius:var(--r);
  border:1px solid var(--line);background:var(--surface);
  color:var(--ink);font-size:14px;font-family:inherit;font-weight:400;
  line-height:1.4;text-align:left;cursor:pointer;
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease)}
.cs-btn:hover{border-color:var(--line-strong);background:var(--surface)}
.cs-btn[aria-expanded="true"],.cs-btn:focus-visible{outline:none;
  border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.cs-btn svg{flex:0 0 auto;color:var(--ink-4);transition:transform .2s var(--ease)}
.cs-btn[aria-expanded="true"] svg{transform:rotate(180deg)}
.cs-list{position:absolute;z-index:55;top:calc(100% + 6px);left:0;right:0;
  margin:0;padding:6px;list-style:none;border-radius:var(--r-md);
  border:1px solid var(--line);background:var(--surface-solid);
  box-shadow:var(--shadow);max-height:264px;overflow-y:auto;
  opacity:0;transform:translateY(-4px);transform-origin:top center;
  pointer-events:none;transition:opacity .14s var(--ease),transform .14s var(--ease)}
/* A closed list is hidden by opacity, but it is still LAID OUT — absolutely
   positioned below its button and as tall as its options. Inside anything with
   overflow:auto (every dialog) that area counts toward scrollHeight, so a popup
   whose content fitted comfortably still scrolled by the height of the tallest
   closed dropdown in it. visibility:hidden was not enough: it stops the
   painting, not the layout, and the box kept its place in the scroll area.
   Collapsing it to zero height does take it out, and the height is restored on
   open — the fade and slide still run, only the growth is instant. */
.cs-list{visibility:hidden;height:0;padding-top:0;padding-bottom:0;overflow:hidden}
.cs-list.is-open{opacity:1;transform:translateY(0);pointer-events:auto;visibility:visible;
  height:auto;padding-top:6px;padding-bottom:6px;overflow-y:auto}
.cs-opt{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:8px 10px;border-radius:var(--r-sm);font-size:14px;color:var(--ink-2);
  cursor:pointer;transition:background .12s var(--ease),color .12s var(--ease)}
.cs-opt:hover,.cs-opt.is-active{background:var(--surface-2);color:var(--ink)}
.cs-opt[aria-selected="true"]{color:var(--accent-ink);font-weight:600}
.cs-opt-check{flex:0 0 auto;opacity:0;color:var(--accent)}
.cs-opt[aria-selected="true"] .cs-opt-check{opacity:1}
@media (prefers-reduced-motion:reduce){.cs-list{transition:none}.cs-btn svg{transition:none}}

/* Buttons: primary is the one solid blue; secondary is white with a hairline;
   8px radius, 40px tall. Not pills. */
button{min-height:40px;font-family:inherit;cursor:pointer;border:1px solid transparent;border-radius:var(--r);
  padding:8px 16px;font-size:14px;font-weight:500;background:var(--accent);color:#fff;
  line-height:1.4;transition:background .15s var(--ease),border-color .15s var(--ease),transform .1s var(--ease)}
button svg{vertical-align:-3px;margin-left:3px}
button:hover{background:var(--accent-hover)}
button:active{transform:scale(.99)}
button:disabled{background:var(--surface-3);color:var(--ink-5);cursor:not-allowed;transform:none}
button.ghost{background:var(--surface);border-color:var(--line);color:var(--ink)}
button.ghost:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink)}
button.danger{background:var(--surface);border-color:var(--line);color:var(--bad-ink)}
button.danger:hover{background:var(--bad-soft);border-color:var(--bad-line)}
button.icon{width:40px;height:40px;padding:0;display:inline-grid;place-items:center;
  background:var(--surface);border-color:var(--line);color:var(--ink-3)}
button.icon:hover{background:var(--surface-2);color:var(--ink)}
button.icon svg{margin:0}

.btnlink{min-height:40px;display:inline-flex;align-items:center;gap:6px;border-radius:var(--r);
  padding:8px 16px;font-size:14px;font-weight:500;text-decoration:none;
  background:var(--accent);color:#fff;border:1px solid transparent;
  transition:background .15s var(--ease)}
.btnlink:hover{background:var(--accent-hover);color:#fff;text-decoration:none}
.btnlink.ghostlink{background:var(--surface);border-color:var(--line);color:var(--ink)}
.btnlink.ghostlink:hover{background:var(--surface-2);color:var(--ink);border-color:var(--line-strong)}
.btnlink svg,.btnlink.ghostlink svg{color:currentColor}

.actions{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
/* The page's primary action, beside a period filter that is deliberately
   quiet. A shadow in the accent's own colour is what separates them: same
   height, same radius, but one sits ON the page and the other IN it. */
.actions button.primary{font-weight:600;box-shadow:0 1px 2px rgba(39,95,252,.24),
  0 6px 16px rgba(39,95,252,.18)}
.actions button.primary:hover{box-shadow:0 1px 2px rgba(39,95,252,.28),
  0 8px 20px rgba(39,95,252,.24)}
.row{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end}
.row>*{flex:1;min-width:150px}
.row>.narrow{flex:0 0 132px;min-width:132px}

/* ── messages ─────────────────────────────────────────────────────────── */
.ok:not(.pill),.err:not(.pill){display:flex;gap:9px;align-items:flex-start;margin:0 0 14px;padding:10px 14px;
  border-radius:var(--r-md);font-size:13px;font-weight:500;border:0;color:var(--ink-2)}
.ok:not(.pill)::before,.err:not(.pill)::before{content:'';width:8px;height:8px;border-radius:99px;
  flex:0 0 auto;margin-top:5px}
.ok:not(.pill){background:var(--ok-soft)}
.ok:not(.pill)::before{background:var(--ok)}
.err:not(.pill){background:var(--bad-soft)}
.err:not(.pill)::before{background:var(--bad)}

/* ── badges & pills ─────────────────────────────────────────────────────
   Soft tint + saturated text, fully rounded, no border, no leading dot. */
.badge{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:99px;
  font-size:12px;font-weight:500;letter-spacing:0;border:0;white-space:nowrap;line-height:1.35;
  background:var(--surface-3);color:var(--ink-3)}
.badge.live{background:var(--ok-soft);color:var(--ok-ink)}
.badge.wip{background:var(--surface-3);color:var(--ink-3)}
.badge.new{background:var(--purple-soft);color:var(--purple)}
.badge.muted-badge{background:var(--surface-3);color:var(--ink-4)}
/* The mail-administration tab strip: one row of links under the page title,
   the active one carrying the accent underline. No JS — each tab is a route. */
.subtabs{display:flex;gap:2px;margin:0 0 18px;border-bottom:1px solid var(--line-soft);flex-wrap:wrap}
.subtab{display:inline-flex;align-items:center;padding:9px 14px;font-size:13.5px;font-weight:500;color:var(--ink-3);text-decoration:none;border-bottom:2px solid transparent;margin-bottom:-1px}
.subtab:hover{color:var(--ink)}
.subtab.is-on{color:var(--accent-ink);border-bottom-color:var(--accent)}
.pill{display:inline-flex;align-items:center;font-size:12px;font-weight:500;color:var(--ink-3);
  border:0;background:var(--surface-3);border-radius:99px;padding:3px 10px;white-space:nowrap;line-height:1.35}
.pill.hot{color:var(--bad-ink);background:var(--bad-soft);font-weight:500}
/* Status pills carry a leading dot; it is centred on the text, not floated. */
.pill.ok,.pill.err{gap:6px;color:var(--ok-ink);background:var(--ok-soft)}
.pill.err{color:var(--bad-ink);background:var(--bad-soft)}
.pill.ok::before,.pill.err::before{content:'';width:6px;height:6px;border-radius:99px;
  flex:0 0 auto;background:currentColor;opacity:.85}
/* Role tags: one colour per tier, assembled from the semantic triplets. */
.pill.role{font-weight:500;border:1px solid transparent}
.pill.role-platform{color:var(--accent-ink,var(--accent));background:var(--accent-soft);border-color:var(--accent-line)}
.pill.role-admin{color:var(--info-ink);background:var(--info-soft);border-color:var(--info-line)}
.pill.role-support{color:var(--warn-ink);background:var(--warn-soft);border-color:var(--warn-line)}
.pill.role-owner{color:var(--ok-ink);background:var(--ok-soft);border-color:var(--ok-line)}
.pill.role-member{color:var(--ink-3);background:var(--surface-3);border-color:var(--line)}
/* Promote / restrict on a login row: a small select and a quiet button. */
.rolepick{display:flex;gap:6px;align-items:center;margin:0}
.rolepick select{min-height:28px;padding:0 26px 0 8px;font-size:12px;width:auto}
.pill.money{font-family:inherit;font-variant-numeric:tabular-nums;color:var(--ink-2)}

/* ── progress ─────────────────────────────────────────────────────────── */
.bar{height:6px;border-radius:99px;background:var(--line-soft);overflow:hidden;margin:12px 0 7px}
.bar>span{display:block;height:100%;border-radius:99px;background:var(--accent)}
.pct{font-size:12px;font-weight:500;color:var(--ink-2)}

/* ── tables ─────────────────────────────────────────────────────────────
   Header row on the muted surface in 12px medium grey (not uppercase); 52px
   rows separated by the softest divider. The card provides the frame. */
table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;
  border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;margin:4px 0 12px}
th{background:var(--surface-2);color:var(--ink-3);font-weight:500;font-size:12px;
  letter-spacing:0;text-transform:none;text-align:left;padding:10px 12px;
  border-bottom:1px solid var(--line)}
td{padding:12px;border-bottom:1px solid var(--line-soft);color:var(--ink-2);
  background:var(--surface);vertical-align:middle;height:52px}
tr:last-child td{border-bottom:none}
tbody tr:hover td{background:var(--surface-2)}
td.k{color:var(--ink-4);width:150px;font-weight:500;font-size:12px;white-space:nowrap;
  background:var(--surface)}

/* ── nav tabs (secondary, inside a page) ────────────────────────────────
   Segmented control: a tinted track, the active segment lifted to white. */
.pnav{width:max-content;max-width:100%;display:flex;gap:2px;margin:0 0 20px;padding:3px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface-3);
  overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none}
.pnav::-webkit-scrollbar{display:none}
.pnav a{min-height:30px;display:flex;align-items:center;padding:0 12px;font-size:13px;font-weight:500;
  color:var(--ink-4);border-radius:var(--r-sm);white-space:nowrap;text-decoration:none;
  transition:color .15s var(--ease),background .15s var(--ease)}
.pnav a:hover{color:var(--ink);text-decoration:none}
.pnav a[aria-current='page']{background:var(--surface);color:var(--ink);font-weight:600;
  box-shadow:0 1px 2px rgba(16,24,40,.08)}

/* ── filter chips ─────────────────────────────────────────────────────── */
.chips{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;align-items:center}
.chips a{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:500;
  min-height:32px;padding:0 12px;border-radius:var(--r);text-decoration:none;border:1px solid var(--line);
  background:var(--surface);color:var(--ink-3);
  transition:border-color .13s,background .13s,color .13s}
.chips a:hover{border-color:var(--line-strong);color:var(--ink);text-decoration:none}
.chips a[aria-current='true']{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-ink);font-weight:600}
.chips a .c{font-variant-numeric:tabular-nums;font-size:11.5px;opacity:.7;font-weight:500}
.chips a[aria-current='true'] .c{opacity:.9}

/* ── filter panel ───────────────────────────────────────────────────────
   The summary strip of the list card: total on the left, search + filter on
   the right, on the muted surface. */
.fbar{margin-bottom:16px;border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--surface);box-shadow:none;overflow:hidden}
.fbar>summary{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:48px;
  padding:8px 12px 8px 14px;cursor:pointer;list-style:none;user-select:none;font-size:13px;color:var(--ink-3);
  background:var(--surface-2)}
.fbar>summary::-webkit-details-marker{display:none}
.fbar>summary:hover{color:var(--ink)}
.fbar-ic{display:grid;place-items:center;color:var(--ink-4)}
.fbar-cur{display:inline-flex;align-items:center;gap:6px;color:var(--ink)}
.fbar-cur b{font-weight:600}
.fbar-cur .c{font-variant-numeric:tabular-nums;font-size:12px;font-weight:600;
  padding:1px 8px;border-radius:99px;background:var(--surface-3);color:var(--ink-3)}
.fbar-tag{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:500;
  padding:3px 10px;border-radius:99px;background:var(--surface-3);color:var(--ink-3);text-decoration:none}
.fbar-tag span{opacity:.55;font-size:10px}
a.fbar-tag:hover{color:var(--ink);text-decoration:none}
.fbar-tag.is-quiet{background:transparent;box-shadow:inset 0 0 0 1px var(--line);color:var(--ink-4)}
.fbar-spacer{flex:1 1 auto}
.fbar-lbl{font-size:13px;font-weight:500;color:var(--ink-2)}
.fbar-chev{display:grid;place-items:center;width:28px;height:28px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);color:var(--ink-3);transition:transform .2s var(--ease)}
.fbar[open] .fbar-chev{transform:rotate(180deg)}
.fbar[open]>summary{border-bottom:1px solid var(--line)}
.fbar-body{padding:12px 14px 14px;display:flex;flex-direction:column;gap:12px}
.fbar-form{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.fbar-form input[type='search']{flex:1 1 220px;min-width:180px;min-height:36px}
.fbar-form select,.fbar-form .cs{flex:0 0 auto;width:auto;min-width:150px}
.fbar-form .cs-btn{width:auto;min-width:150px;min-height:36px}
.fbar-form button{flex:0 0 auto;min-height:36px;background:var(--surface);
  border-color:var(--line);color:var(--ink);font-weight:500}
.fbar-form button:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink)}
.fbar-body .chips{margin:0;gap:5px}
.fbar-body .chips a,.fbar-body .chipmore>summary{min-height:30px;padding:0 10px;font-size:12.5px}
.fbar-body .chips a[aria-current='true']{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-ink)}
.fbar-body .chips a[aria-current='true'] .c{color:inherit;opacity:.9}
.fbar-reset{align-self:flex-start;font-size:12.5px;color:var(--ink-3)}

/* ── toolbar ────────────────────────────────────────────────────────────── */
.toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-lg);padding:12px 14px;margin-bottom:16px;box-shadow:none}
.toolbar input[type='search'],.toolbar input[type='text']{flex:1 1 240px;min-width:190px}
.toolbar select{flex:0 0 auto;width:auto;min-width:158px}
.toolbar label{display:inline-flex;align-items:center;margin:0;flex:0 0 auto;
  font-size:12.5px;color:var(--ink-3);white-space:nowrap}
.toolbar button{flex:0 0 auto}
.toolbar input[type='date']{flex:0 0 auto;width:auto;min-width:150px}
.toolbar .cs{flex:0 0 auto;width:auto;min-width:170px}
.toolbar .cs-btn{width:auto;min-width:170px}

/* ── record list ────────────────────────────────────────────────────────
   Rows in one bordered container rather than a stack of floating cards:
   the list IS the card, and each row is 1px of divider from the next. */
.clist{display:flex;flex-direction:column;gap:0;margin:0;padding:0;list-style:none;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}
.crow{background:var(--surface);border:0;border-bottom:1px solid var(--line-soft);border-radius:0;
  padding:14px 18px;display:flex;align-items:center;gap:14px;box-shadow:none;min-height:52px;
  transition:background .15s var(--ease)}
.crow:last-child{border-bottom:0}
.crow.is-new{box-shadow:none}
.crow.is-overdue{box-shadow:inset 3px 0 0 var(--bad)}
.crow{position:relative}
/* The pointer cursor and the hover tint are a PROMISE that the row opens
   something, so they are scoped to rows that actually do. /portail/comptes
   moved its "Gérer" action into the row kebab and left the name as plain text:
   the row went on inviting a click and answered none. A row whose only control
   is a delete button (the custom-field list) never had anything to open. */
.crow:has(.nm a,.nm button,[data-dialog-open],[data-href]){cursor:pointer}
.crow:has(.nm a,.nm button,[data-dialog-open],[data-href]):hover{
  transform:none;background:var(--surface-2);box-shadow:none;border-color:var(--line-soft)}
.crow .nm a::after{content:'';position:absolute;inset:0;z-index:1}
/* The same overlay for a row whose destination is a DIALOG rather than a page
   (the accounts list). It has to be a real <button> — the thing it opens is
   not a URL — so it is stripped back to the anchor's appearance and stretched
   the same way, keeping one target and one tab stop per row. */
.crow .nm button{appearance:none;background:none;border:0;padding:0;margin:0;
  font:inherit;color:inherit;text-align:left;cursor:pointer;min-height:0}
.crow .nm button::after{content:'';position:absolute;inset:0;z-index:1}
.crow .nm button:focus-visible{outline:none}
.crow .right,.crow .meta a,.crow .taglist{position:relative;z-index:2}

.row-go{flex:0 0 auto;width:28px;height:28px;display:grid;place-items:center;border-radius:var(--r-sm);
  background:transparent;color:var(--ink-5);transition:color .15s var(--ease),background .15s var(--ease)}
.row-go svg{width:15px;height:15px}
.crow:hover .row-go{background:var(--surface-3);color:var(--ink);transform:none}

.crow .who{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.crow .nm{font-size:14px;font-weight:600;color:var(--ink);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crow .nm a{color:inherit;font-weight:inherit;text-decoration:none}
.crow:hover .nm a{color:var(--ink)}
.crow:focus-within{outline:2px solid var(--accent);outline-offset:-2px}
.crow .nm a:focus-visible{outline:none}
.crow .meta{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--ink-4);margin-top:3px}
.crow .msg{color:var(--ink-3);font-size:13px;margin:6px 0 0;line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-clamp:2;overflow:hidden}
.crow>:first-child{flex:1 1 auto;min-width:0}
.crow .right{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.row-action{min-height:32px;display:inline-flex;align-items:center;gap:6px;padding:0 12px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);
  color:var(--ink);font-size:13px;font-weight:500;white-space:nowrap;text-decoration:none}
.row-action:hover{background:var(--surface-2);color:var(--ink);text-decoration:none;border-color:var(--line-strong)}

/* Avatar: 28px circle, initials on a soft tint. */
.av-sm{width:28px;height:28px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  background:var(--surface-3);color:var(--ink-3);font-size:10.5px;font-weight:600;letter-spacing:.02em}

/* ── card grid variant ──────────────────────────────────────────────────── */
.clist.is-grid{display:grid;gap:16px;background:transparent;border:0;border-radius:0;overflow:visible;
  grid-template-columns:repeat(auto-fill,minmax(272px,1fr))}
.clist.is-grid>.crow{flex-direction:column;align-items:stretch;gap:12px;padding:16px 18px;
  border:1px solid var(--line);border-radius:var(--r-lg)}
.clist.is-grid>.crow:hover{border-color:var(--line-strong);background:var(--surface)}
.clist.is-grid>.crow>:first-child{flex:0 0 auto}
.clist.is-grid>.crow .right{margin-top:auto;padding-top:2px}
.clist.is-grid>.crow .who{align-items:center;gap:10px;flex-wrap:nowrap}
.clist.is-grid>.crow .meta{display:block;margin-top:8px}
.clist.is-grid>.crow .meta>span{display:block;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;line-height:1.55}
.clist.is-grid>.crow .nm{font-size:14px;white-space:normal;overflow:visible}

/* ── site status icon ───────────────────────────────────────────────────── */
.sitedot{width:28px;height:28px;border-radius:var(--r);flex:0 0 auto;
  display:grid;place-items:center;background:var(--surface-3);color:var(--ink-4)}
.sitedot svg{width:15px;height:15px}
.sitedot.is-up{background:var(--ok-soft);color:var(--ok)}
.sitedot.is-down{background:var(--bad-soft);color:var(--bad)}
@media (prefers-reduced-motion:no-preference){
  .sitedot.is-down{animation:sitepulse 2s var(--ease) infinite}
}
@keyframes sitepulse{0%,100%{box-shadow:0 0 0 0 var(--bad-soft)}50%{box-shadow:0 0 0 4px transparent}}

.star{width:36px;height:36px;display:grid;place-items:center;background:none;border:0;padding:0;
  font-size:15px;line-height:1;color:var(--line-strong);
  cursor:pointer;transition:color .13s ease,transform .1s ease}
.star:hover{background:none;color:var(--ink-4);transform:scale(1.1)}
.star.on{color:var(--flag)}
.star.on:hover{background:none;color:var(--flag)}

/* ── tags ─────────────────────────────────────────────────────────────── */
.taglist{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 4px}
.tag{display:inline-flex;align-items:center;gap:2px;font-size:12px;font-weight:500;
  padding:2px 4px 2px 9px;border-radius:99px;background:var(--purple-soft);border:0;color:var(--purple)}
.tag .x{background:none;border:0;padding:0 4px;font-size:13px;line-height:1;
  min-width:24px;min-height:24px;color:inherit;opacity:.6;cursor:pointer;border-radius:99px}
.tag .x:hover{background:none;opacity:1;color:var(--bad)}
a.tagchip{font-size:12px;font-weight:500;padding:3px 10px;border-radius:99px;
  text-decoration:none;background:var(--surface-3);border:0;color:var(--ink-3)}
a.tagchip:hover{background:var(--purple-soft);color:var(--purple);text-decoration:none}

/* ── timeline ─────────────────────────────────────────────────────────── */
.tl{list-style:none;margin:0;padding:0}
.tl li{position:relative;padding:0 0 20px 30px;border-left:1px solid var(--line);margin-left:10px}
.tl li:last-child{border-left-color:transparent;padding-bottom:0}
.tl .dot{position:absolute;left:-10px;top:0;width:20px;height:20px;border-radius:50%;
  border:1px solid var(--line-strong);background:var(--surface);display:grid;place-items:center;
  font-size:10.5px;font-weight:600;color:var(--ink-4);font-variant-numeric:tabular-nums}
.tl li.done .dot{background:var(--ok);border-color:var(--ok);color:#fff}
.tl li.current .dot{background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:0 0 0 3px var(--accent-soft)}
.tl .ph{font-weight:600;font-size:13.5px;color:var(--ink-3);margin:1px 0 0}
.tl li.done .ph,.tl li.current .ph{color:var(--ink)}
.tl .de{margin:2px 0 0;font-size:12.5px;color:var(--ink-4);line-height:1.5}
.tl .dt{font-size:12px;color:var(--ink-4);margin-top:3px}

/* ── activity feed ────────────────────────────────────────────────────── */
.feed{list-style:none;margin:0;padding:0}
.feed li{position:relative;padding:0 0 18px 30px;border-left:1px solid var(--line);margin-left:8px}
.feed li:last-child{border-left-color:transparent;padding-bottom:0}
.feed .fi{position:absolute;left:-9px;top:1px;width:18px;height:18px;border-radius:50%;
  background:var(--surface);border:1px solid var(--line-strong);display:grid;place-items:center;font-size:9px;color:var(--ink-4)}
.feed li[data-kind='call'] .fi{border-color:transparent;color:var(--info);background:var(--info-soft)}
.feed li[data-kind='email'] .fi{border-color:transparent;color:var(--accent);background:var(--accent-soft)}
.feed li[data-kind='meeting'] .fi{border-color:transparent;color:var(--ok);background:var(--ok-soft)}
.feed li[data-kind='status'] .fi{border-color:transparent;color:var(--warn);background:var(--warn-soft)}
.feed .fk{font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4)}
.feed .fb{margin:2px 0 0;color:var(--ink-2);font-size:13.5px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.feed .ft{font-size:12px;color:var(--ink-4);margin-top:3px}

/* ── custom form fields ─────────────────────────────────────────────────── */
.fieldgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px}
.fieldcard{min-width:0;padding:12px 14px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2)}
.fieldcard.is-long{grid-column:1/-1}
.fieldcard-k{font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4);margin:0 0 4px}
.fieldcard-v{margin:0;font-size:14px;font-weight:500;color:var(--ink);line-height:1.45;overflow-wrap:anywhere}
.fieldcard.is-long .fieldcard-v{font-size:14px;font-weight:400;color:var(--ink-2);white-space:pre-wrap}

/* ── activity log ─────────────────────────────────────────────────────── */
.log{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.log li{position:relative;display:flex;gap:11px;padding:11px 2px;border-bottom:1px solid var(--line-soft)}
/* A row that names a record opens it: an invisible link stretched over the
   whole row, the same trick .crow uses, so the target is the row and not four
   coloured words in the middle of a sentence. */
.log li.is-link{cursor:pointer}
.log .log-go{position:absolute;inset:0;z-index:1;border-radius:var(--r-sm)}
.log li.is-link:hover{background:var(--surface-2)}
.log li.is-link:focus-within{outline:2px solid var(--accent);outline-offset:-2px;border-radius:var(--r-sm)}
.log .log-go:focus-visible{outline:none}
.log li.is-link:hover .log-subject{text-decoration:underline;text-underline-offset:2px}
.log li:last-child{border-bottom:0;padding-bottom:0}
.log li:first-child{padding-top:0}
.log-av{width:28px;height:28px;border-radius:50%;flex:0 0 auto;display:grid;place-items:center;
  background:var(--surface-3);color:var(--ink-3);font-size:10.5px;font-weight:600}
.log-body{min-width:0;display:flex;flex-direction:column;gap:2px}
.log-line{font-size:13.5px;color:var(--ink-2);line-height:1.5}
.log-line strong{color:var(--ink);font-weight:600}
.log-line .badge{margin-left:5px;vertical-align:1px}
.log-subject{color:var(--ink);font-weight:500}
.log-change{font-size:12.5px;color:var(--ink-4)}
.log-from{text-decoration:line-through;opacity:.75}
.log-to{color:var(--ink-2)}
.log-at{font-size:12px;color:var(--ink-4);font-variant-numeric:tabular-nums}

/* ── segmented control ────────────────────────────────────────────────── */
.seg{display:inline-flex;flex-wrap:wrap;border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;margin:5px 0 0;padding:3px;background:var(--surface-3)}
.seg input{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.seg label{min-height:30px;margin:0;padding:6px 12px;font-size:13px;font-weight:500;cursor:pointer;
  color:var(--ink-4);border:0;border-radius:var(--r-sm);user-select:none;transition:background .13s,color .13s}
.seg label:hover{color:var(--ink)}
.seg input:checked+label{background:var(--surface);color:var(--ink);font-weight:600;box-shadow:0 1px 2px rgba(16,24,40,.08)}
.seg input:focus-visible+label{outline:2px solid var(--accent);outline-offset:-2px}

/* ── password field ───────────────────────────────────────────────────── */
.pw{position:relative;display:flex;align-items:stretch}
.pw input[type='text'],.pw input[type='password']{flex:1;padding-right:40px;font-family:'JetBrains Mono',monospace;font-size:13px}
.pw>input[type='checkbox']{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.pw .eye{position:absolute;right:1px;top:1px;bottom:1px;width:36px;display:grid;place-items:center;
  cursor:pointer;color:var(--ink-4);margin:0;border-radius:0 var(--r-sm) var(--r-sm) 0;transition:color .13s}
.pw .eye:hover{color:var(--ink)}
.pw>input[type='checkbox']:focus-visible+input+.eye{outline:2px solid var(--accent);outline-offset:-2px}
.pw>input[type='checkbox']:not(:checked)+input[type='text']{-webkit-text-security:disc;text-security:disc}
.pw .eye .off{display:none}
.pw>input[type='checkbox']:checked+input+.eye .on{display:none}
.pw>input[type='checkbox']:checked+input+.eye .off{display:block}

/* ── code block ───────────────────────────────────────────────────────── */
pre.snip{max-width:100%;background:var(--code-bg);border:0;border-radius:var(--r-md);
  padding:12px 14px;overflow-x:auto;font-size:12px;line-height:1.65;color:var(--code-ink);
  font-family:'JetBrains Mono',ui-monospace,Menlo,monospace;margin:9px 0}

/* ── layout helpers ───────────────────────────────────────────────────── */
.split{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:16px;align-items:start}
.detail{display:grid;gap:16px;align-items:stretch;grid-template-columns:minmax(0,1fr) minmax(340px,400px)}
.factlist{display:flex;flex-wrap:wrap;gap:10px 28px;margin:14px 0 0}
.factlist>div{min-width:0}
.factlist dt{font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4);margin:0 0 2px}
.factlist dd{margin:0;font-size:13.5px;color:var(--ink);overflow-wrap:anywhere}
.factlist>div:last-child:nth-child(n+3){flex:1 1 100%}

.actpanel{display:grid;gap:10px}
.actpanel-top{display:flex;gap:8px;flex-wrap:wrap}
.actpanel-top .btnlink{flex:1 1 auto;justify-content:center;min-height:40px}
.actpanel-fields{display:flex;flex-direction:column;gap:8px;margin:0}
.actpanel-save{justify-content:flex-end}
.actpanel-save button{flex:0 0 auto;min-height:36px;padding:0 14px}
.actpanel-row{display:flex;align-items:center;gap:8px;margin:0}
.actpanel-row label{flex:0 0 62px;margin:0;font-size:12.5px;color:var(--ink-3)}
.actpanel-row input,.actpanel-row select,.actpanel-row .cs{flex:1 1 auto;min-height:36px;width:auto;min-width:0}
.actpanel-row button{flex:0 0 auto;min-height:36px;padding:0 12px}
.actpanel-note{margin:0;font-size:12px}
.actpanel-more{border-top:1px solid var(--line);padding-top:10px;margin:0}
.actpanel-more>summary{display:flex;align-items:center;gap:7px;cursor:pointer;
  font-size:13px;font-weight:500;color:var(--ink-2);list-style:none;padding:2px 0}
.actpanel-more>summary::-webkit-details-marker{display:none}
.actpanel-more>summary:hover{color:var(--ink)}
.actpanel-more[open]>summary{margin-bottom:10px}
.actpanel-more .hint{margin:8px 0 0}
.danger-more>summary{color:var(--ink-4)}
.danger-more>summary:hover{color:var(--bad)}
/* Both columns are flex stacks whose LAST card absorbs the leftover height, so
   the two columns always end on the same line — no short column dangling above
   the other. See DESIGN.md, "Columns end together". */
.detail-main,.detail-side{display:flex;flex-direction:column;gap:16px;min-width:0}
.detail-main>:last-child,.detail-side>:last-child{flex:1 1 auto}
.detail-side{grid-column:2}
.detail-main{grid-column:1;grid-row:1}
.detail .card{margin:0}
.detail-lead{margin:0 0 16px}
.pane-pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px 24px}
.pane-pair>section{min-width:0}
.pane-pair h2{margin-bottom:2px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(228px,1fr));gap:16px}
hr{border:0;border-top:1px solid var(--line);margin:24px 0}

/* Section heading: an h2 row with an optional "See all" link at the right. */
.section-heading{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:0 0 10px}
.section-heading:not(:first-child){margin-top:16px}
.stats+.section-heading,.card+.section-heading,.metrics+.section-heading{margin-top:16px}
.section-heading .eyebrow{display:none}
.section-heading h2{font-size:14px;color:var(--ink-3);font-weight:600}
.section-heading>a{min-height:0;display:inline-flex;align-items:center;gap:4px;padding:0;
  font-size:13px;font-weight:500;white-space:nowrap;color:var(--ink-3)}
.section-heading>a:hover{color:var(--ink)}
.section-heading>a svg{width:14px;height:14px}
.support-note{width:max-content;max-width:100%;margin:32px auto 0;padding:0;
  border:0;background:none;color:var(--ink-4);font-size:13px;text-align:center}
.support-note a{color:var(--ink-2);text-decoration:underline;text-underline-offset:3px}

.empty{text-align:center;padding:40px 24px;color:var(--ink-3)}
.empty .ei{width:40px;height:40px;margin:0 auto 12px;border-radius:var(--r-md);display:grid;
  place-items:center;background:var(--surface-3);color:var(--ink-4)}
.empty .ei svg{width:18px;height:18px}

details summary{user-select:none;font-size:13px;font-weight:500;color:var(--ink-2);
  cursor:pointer;display:inline-flex;align-items:center;gap:6px;padding:2px 0}
details summary:hover{color:var(--accent)}
details summary::marker{color:var(--ink-4)}
.card>details{margin-top:12px}
.card>details:first-child{margin-top:0}
.card>details+details{margin-top:6px}
.card>details .mread-back,.card>details #mcomp-t{display:none}
.card>details>summary{min-height:40px;padding:0 14px;gap:10px;border:1px solid var(--line);
  border-radius:var(--r);background:var(--surface);color:var(--ink);font-weight:500;width:max-content;max-width:100%;
  list-style:none;transition:background .15s var(--ease),border-color .15s var(--ease),color .15s var(--ease)}
.card>details>summary::-webkit-details-marker{display:none}
.card>details>summary::after{content:'›';font-size:17px;font-weight:400;line-height:1;color:var(--ink-4);
  transform:rotate(90deg);transition:transform .15s var(--ease)}
.card>details>summary:hover{border-color:var(--line-strong);background:var(--surface-2);color:var(--ink)}
.card>details[open]>summary{border-color:transparent;background:var(--accent-soft);color:var(--accent-ink)}
.card>details[open]>summary::after{transform:rotate(-90deg);color:inherit}

.pager{display:flex;gap:8px;align-items:center;justify-content:center;margin-top:16px}
.pager a,.pager span{min-height:32px;display:inline-flex;align-items:center;font-size:13px;padding:0 12px;border-radius:var(--r);
  border:1px solid var(--line);background:var(--surface);text-decoration:none;color:var(--ink)}
.pager a:hover{border-color:var(--line-strong);background:var(--surface-2);text-decoration:none}
.pager span{color:var(--ink-4);border-color:transparent;background:none;font-variant-numeric:tabular-nums}

/* ── public tracking page ────────────────────────────────────────────── */
.track{width:min(720px,calc(100% - 40px));margin:0 auto;padding:56px 0 64px}
.track-head{margin-bottom:24px;padding-bottom:20px;border-bottom:1px solid var(--line)}
.track-head h1{font-size:28px;margin-bottom:10px}
.track-meta{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.track-progress{padding:20px}
.track-headline{margin:0 0 16px;color:var(--ink-2);font-size:14px;line-height:1.6}
.track-pct{display:flex;align-items:baseline;gap:12px;margin:0 0 12px}
.track-pct strong{font-family:inherit;font-size:36px;font-weight:600;line-height:1;color:var(--ink);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.track-pct strong span{font-size:18px;color:var(--ink-3);margin-left:1px}
.track-phase{font-size:14px;font-weight:500;color:var(--ink-3)}
.track-progress .bar{height:8px;margin:0}
.track-due{margin:14px 0 0;padding-top:14px;border-top:1px solid var(--line)}
.track-foot{margin:30px auto 0;max-width:52ch;text-align:center;color:var(--ink-4);font-size:13px;line-height:1.6}
@media (max-width:640px){.track{width:calc(100% - 32px);padding:36px 0 48px}.track-head h1{font-size:24px}.track-pct strong{font-size:32px}}

/* ── login ────────────────────────────────────────────────────────────── */
.auth{min-height:100dvh;position:relative;display:grid;place-items:center;padding:96px 24px 58px;overflow:auto}
.auth>*{position:relative;z-index:1}
.auth-home{position:absolute;top:0;left:0;right:0;width:100%;
  min-height:64px;display:flex;align-items:center;justify-content:space-between;padding:12px 24px;
  border:0;border-bottom:1px solid var(--line);border-radius:0;background:var(--surface);
  box-shadow:none;color:var(--ink-2);font-size:13px;text-decoration:none}
.auth-card{width:100%;max-width:440px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-xl);padding:32px 32px 28px;box-shadow:none}
.auth-brand{display:flex;align-items:center;gap:12px;color:var(--ink);margin-bottom:28px}
.auth-brand img{display:block;width:64px;height:auto}
.auth-brand span{padding-left:12px;border-left:1px solid var(--line);font-size:12px;font-weight:500;color:var(--ink-4)}
.auth-card .eyebrow{display:none}
.auth-card h1{font-size:22px;margin-bottom:6px}
.auth-intro{font-size:14px;line-height:1.55;margin-bottom:20px}
.auth-card .ok,.auth-card .err{margin:0 0 16px}
.auth-form label{font-size:13px;margin-top:14px}
.pw-rules{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.pw-rules li{display:inline-flex;align-items:center;gap:6px;padding:4px 10px 4px 7px;border-radius:999px;font-size:12px;line-height:1.3;color:var(--ink-3);background:var(--surface-2);border:1px solid var(--line);transition:background .15s,color .15s,border-color .15s}
.pw-dot{width:14px;height:14px;border-radius:50%;border:1.5px solid var(--ink-4);flex:0 0 auto;position:relative;transition:background .15s,border-color .15s}
.pw-rules li.is-ok{color:var(--ok-ink);background:var(--ok-soft);border-color:var(--ok-line)}
.pw-rules li.is-ok .pw-dot{background:var(--ok);border-color:var(--ok)}
.pw-rules li.is-ok .pw-dot::after{content:"";position:absolute;left:4px;top:1.5px;width:3px;height:7px;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg)}
.pw-rules li.is-bad{color:var(--bad-ink);background:var(--bad-soft);border-color:var(--bad-line)}
.pw-rules li.is-bad .pw-dot{border-color:var(--bad)}
.pw-match{min-height:1.4em;margin:6px 0 0}
.pw-match.is-ok{color:var(--ok-ink)}
.pw-match.is-bad{color:var(--bad-ink)}
.auth-submit{width:100%;display:flex;align-items:center;justify-content:center;gap:7px;margin-top:20px}
.auth-submit svg{margin:0}
.auth-support{margin-top:22px;padding-top:18px;border-top:1px solid var(--line);color:var(--ink-4);font-size:13px;text-align:center}
.auth-support a.hint{color:var(--link);text-decoration:underline;text-underline-offset:3px}
.auth-support a.hint:hover{color:var(--link-hover)}
.auth-secure{position:absolute;bottom:18px;left:50%;transform:translateX(-50%);display:flex;align-items:center;
  gap:7px;padding:0;border-radius:0;background:none;border:0;color:var(--ink-4);font-size:12px;white-space:nowrap}

/* ── in-place navigation ──────────────────────────────────────────────── */
html.is-loading::before{content:'';position:fixed;top:0;left:0;right:0;height:2px;z-index:9999;
  background:var(--accent);transform-origin:left;animation:pnav 6s cubic-bezier(.1,.7,.3,1) forwards}
/* Fills fast at first, then creeps towards the end and waits there: a bar
   that loops reads as the request restarting, which on a slow link it is not. */
@keyframes pnav{0%{transform:scaleX(0)}30%{transform:scaleX(.6)}70%{transform:scaleX(.85)}100%{transform:scaleX(.95)}}
/* The work area does NOT dim the instant a request starts: on a fast link
   that reads as a flash, not as feedback. It fades only when a request has
   already taken a quarter second — the bar above is the immediate cue. */
.work{transition:opacity .2s ease-out}
html.is-loading .work{opacity:.8;transition-delay:.25s}
h1:focus{outline:none}
/* The in-place swap runs inside a view transition when the browser has one.
   The rail and the page header keep their own names, so they hold still
   while only the workbench cross-fades — one instrument, new reading. */
.side{view-transition-name:portal-rail}
.topbar{view-transition-name:portal-topbar}
.mail-side{view-transition-name:portal-mail-rail}
::view-transition-old(root),::view-transition-new(root){animation-duration:.16s}
::view-transition-group(portal-rail),::view-transition-group(portal-topbar),::view-transition-group(portal-mail-rail){animation-duration:.16s}
@media (prefers-reduced-motion:reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none !important}
}

/* ── responsive ─────────────────────────────────────────────────────────── */
@media (max-width:1000px){
  .split{grid-template-columns:minmax(0,1fr)}
  .detail{grid-template-columns:minmax(0,1fr)}
  .detail-side,.detail-main{grid-column:1;grid-row:auto}
  .crow{flex-wrap:wrap;align-items:flex-start}
  .crow>:first-child{flex:1 1 100%}
  .crow .right{margin-top:4px}
}
@media (max-width:920px){
  .side{top:0;left:0;bottom:0;width:min(288px,84vw);
    transform:translateX(-100%);box-shadow:var(--shadow-lg);transition:transform .24s var(--ease)}
  .nav-toggle:checked~.side{transform:none}
  .nav-scrim{display:block;position:fixed;inset:0;z-index:55;background:var(--scrim);
    opacity:0;pointer-events:none;transition:opacity .24s var(--ease)}
  .nav-toggle:checked~.nav-scrim{opacity:1;pointer-events:auto}
  .nav-open,.nav-close{display:grid;place-items:center;width:36px;height:36px;flex:0 0 auto;
    border:1px solid var(--line);border-radius:var(--r);background:var(--surface);color:var(--ink);cursor:pointer}
  .nav-open:hover,.nav-close:hover{background:var(--surface-2)}
  .nav-toggle:focus-visible~.topnav .nav-open{outline:2px solid var(--accent);outline-offset:2px}
  .topnav{position:sticky;top:0;z-index:50;display:flex;align-items:center;gap:12px;
    padding:10px 16px;background:var(--surface);border-bottom:1px solid var(--line)}
  /* With the tab bar carrying navigation, the top bar keeps only the
     workspace avatar, right where a thumb expects the account; it opens the
     same drawer the More tab does, so the burger is redundant. */
  /* The tab bar carries navigation and the account avatar, so the phone
     top bar has no job left; the page title becomes the first thing seen. */
  .shell .topnav{display:none}
  .topnav-ws{display:flex;align-items:center;gap:9px;min-width:0}
  .canvas{margin-left:0}
  /* Bottom padding clears the floating tab bar AND the home indicator, so
     the last row of any list is reachable rather than sitting under a tab. */
  .work{padding:20px 16px calc(var(--tabbar-h) + 32px + env(safe-area-inset-bottom,0px))}
  /* The bar is fixed, so it sits ON the last ~62px of the viewport. Padding
     only buys clearance at the END of a document; anything the BROWSER scrolls
     to — a focused field, an #anchor, the heading render() focuses after a
     page swap — could still be parked underneath it, where a tap silently
     lands on a tab instead of the control. scroll-padding keeps those landings
     above the bar. */
  html{scroll-padding-bottom:calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom,0px))}

  /* The tab bar becomes the primary navigation here. It floats over the
     content on its own layer, above the scrim's z-index sibling but below
     the drawer, so opening More slides the panel over it. */
  .tabbar{position:fixed;left:0;right:0;bottom:0;z-index:56;
    display:flex;align-items:stretch;gap:2px;
    padding:4px 6px calc(4px + env(safe-area-inset-bottom,0px));
    background:var(--tabbar);border-top:1px solid var(--tabbar-line);
    -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}
  /* Reduced transparency: fall back to the solid surface rather than a
     blur, which is decoration once someone has asked for less of it. */
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .tabbar{background:var(--surface)}
  }
  /* The burger is no longer the primary door — More is. It stays as a
     second way in for anyone who has learnt it, but loses its box so it
     reads as a quiet affordance beside the workspace, not a main control. */
  .nav-open{border-color:transparent;background:transparent;color:var(--ink-3)}

  /* ── the drawer as a touch surface ───────────────────────────────────
     It used to be a rarely-opened overflow of a rail sized for a mouse;
     now it is where Sites, Activity, Réglages and the whole KRUZ section
     actually live, so every row in it has to take a thumb. 44px min, and
     rows at the body size rather than the rail's 14px. */
  .nav-open,.nav-close{width:44px;height:44px}
  .side{width:min(320px,88vw);padding:16px 12px calc(16px + env(safe-area-inset-bottom,0px))}
  .side-nav{gap:1px}
  .side-nav a{min-height:46px;height:auto;padding:0 14px;font-size:var(--fs-body);border-radius:var(--r-md)}
  .side-nav svg{width:20px;height:20px}
  .side-signout{min-height:46px;padding:0 14px;font-size:var(--fs-body);border-radius:var(--r-md)}
  .side-signout svg{width:20px;height:20px}
  .side-label{margin:18px 14px 6px}
  .side-tools{min-height:48px;gap:10px}
  .workspace-card{grid-template-columns:minmax(0,1fr)}
  .workspace-hint{grid-column:auto}
  .card:has(table){overflow-x:auto}
  .crow,.toolbar{overflow-x:auto}
  table{min-width:560px}
  table:has(td.k){min-width:0}
  table:has(td.k) td{overflow-wrap:anywhere}
}
@media (max-width:640px){
  /* The body floor on a phone. Bumping the token rather than the element
     carries every size built on the scale up with it. */
  :root{--fs-body:15px;--fs-small:13.5px;--fs-lead:17px;--fs-title:22px}
  body{font-size:var(--fs-body)}
  .work{padding:16px 16px calc(var(--tabbar-h) + 28px + env(safe-area-inset-bottom,0px))}
  /* One row: title left, the page's action top-right where a thumb expects
     it. The subtitle is the one thing dropped: it costs a line on every page
     and the list beneath is what the reader came for. */
  .topbar{align-items:center;gap:12px;height:auto;margin-bottom:14px}
  .topbar h1{font-size:22px}
  .topbar .sub{display:none}
  /* One row WHERE IT FITS. The actions area is flex-shrink:0 by default, and
     the accounting header puts the whole period selector (~520px) in it — on a
     390px screen that alone pushed the document 150px wider than the phone and
     triggered the same zoom-out described at .tablewrap. Letting the header
     wrap costs a line on exactly the pages whose action does not fit, and
     keeps the intended single row everywhere else. */
  .topbar{flex-wrap:wrap}
  .topbar .actions{align-self:center;gap:6px;flex-shrink:1;min-width:0;flex-wrap:wrap}
  .topbar .actions .btnlink{padding:9px 12px;font-size:13.5px;white-space:nowrap}
  /* List strips: the summary note (view name, active and archived counts)
     does not fit beside the count on a phone and spilled out of the card. */
  .lstrip-note{display:none}
  .lcard>.dash-strip{padding:8px 14px 7px}
  .lstrip-right{width:100%}
  .lstrip-right .lsearch{flex:1 1 100%}
  .lstrip-right .lsearch input{width:100%}
  /* Activity's filter chips: one scrollable row instead of a three-line block
     sitting between the search and the first entry. */
  .lchips{padding:6px 14px}
  .lchips .chips{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
  .lchips .chips::-webkit-scrollbar{display:none}
  .lchips .chips a{flex:0 0 auto}
  .card{padding:16px}
  .workspace-card{padding:16px}
  .workspace-form{flex-wrap:wrap}
  .workspace-form .narrow{flex:1 1 100%;min-width:100%}
  .status-card{align-items:flex-start;flex-wrap:wrap}
  .status-action{width:100%;justify-content:center}
  .stats{gap:12px}
  .stat{padding:14px 16px}
  .stat .n{font-size:24px}
  .crow{padding:14px 16px}
  .row-action{width:100%;justify-content:space-between}
  .section-heading{margin-top:20px}
  .pnav{width:100%}
  input,select,textarea{font-size:16px}
  .auth{padding:88px 16px 52px}
  .auth-home{min-height:60px;padding:8px 12px}
  .auth-home img{width:60px}
  .auth-card{max-width:460px;padding:24px 20px 22px}
  .auth-brand{margin-bottom:22px}
  .auth-secure{bottom:9px}
}
@media (max-width:390px){
  .work{padding-inline:12px}
  .auth-home span{padding:0 10px;font-size:12px}
  .auth-card{padding-inline:18px}
}

/* ── language switcher (legacy row) ───────────────────────────────────── */
.lang-switch{display:flex;gap:4px;margin:0 0 12px;padding:3px;background:var(--surface-3);border:1px solid var(--line);border-radius:var(--r)}
.lang-opt{flex:1;min-height:30px;padding:5px 0;border-radius:var(--r-sm);border:0;background:none;color:var(--ink-4);
  font-family:inherit;font-size:11.5px;font-weight:600;letter-spacing:.04em;cursor:pointer;transition:color .15s var(--ease),background .15s var(--ease)}
.lang-opt:hover{background:none;color:var(--ink-2)}
.lang-opt.is-active{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.08)}
.lang-opt.is-active:hover{background:var(--surface);color:var(--ink)}

/* ── appearance switcher ────────────────────────────────────────────────
   A small segmented control: two icon buttons on a tinted track. */
.theme-switch{display:inline-flex;gap:2px;margin:0;padding:3px;background:var(--surface-3);border:1px solid var(--line);border-radius:var(--r)}
.theme-opt{flex:0 0 auto;width:32px;min-height:28px;display:grid;place-items:center;
  padding:0;border-radius:var(--r-sm);border:0;background:none;color:var(--ink-4);
  cursor:pointer;transition:color .15s var(--ease),background .15s var(--ease)}
.theme-opt:hover{background:none;color:var(--ink-2)}
.theme-opt.is-active{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.08)}
.theme-opt.is-active:hover{background:var(--surface);color:var(--ink)}
.theme-opt svg{display:block}

/* ── language dropdown ──────────────────────────────────────────────────── */
.lang-dd-form{margin:0}
.lang-dd{position:relative;width:fit-content}
.lang-dd summary{list-style:none;display:flex;align-items:center;gap:7px;
  min-height:34px;padding:0 10px;border-radius:var(--r);cursor:pointer;
  border:1px solid var(--line);background:var(--surface);color:var(--ink-3);font-size:12.5px;font-weight:600;
  letter-spacing:.02em;transition:color .15s var(--ease),background .15s var(--ease)}
.lang-dd summary::-webkit-details-marker{display:none}
.lang-dd summary:hover,.lang-dd[open] summary{background:var(--surface-2);color:var(--ink)}
.lang-flag{display:block;width:18px;height:13px;flex:0 0 auto;overflow:hidden;border-radius:2px;box-shadow:0 0 0 1px rgba(0,0,0,.12)}
.lang-flag svg{display:block;width:100%;height:100%}
.lang-chevron{transition:transform .18s var(--ease);color:var(--ink-5)}
.lang-dd[open] .lang-chevron{transform:rotate(180deg)}
.lang-dd-menu{position:absolute;top:calc(100% + 6px);right:0;z-index:120;
  min-width:176px;padding:5px;display:flex;flex-direction:column;gap:1px;
  border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-solid);box-shadow:var(--shadow)}
.lang-dd-opt{display:flex;align-items:center;gap:10px;width:100%;min-height:0;
  padding:8px 10px;border:0;border-radius:var(--r-sm);background:none;text-align:left;
  font-size:13.5px;font-weight:500;color:var(--ink-3);cursor:pointer;transition:background .14s var(--ease),color .14s var(--ease)}
.lang-dd-opt:hover{background:var(--surface-2);color:var(--ink)}
.lang-dd-opt[aria-current]{color:var(--ink);font-weight:600}
.side .lang-dd-menu{top:auto;bottom:calc(100% + 6px);right:auto;left:0}
.auth>.lang-dd-form{margin:18px auto 0;width:fit-content}
.auth>.lang-dd-form .lang-dd-menu{right:50%;transform:translateX(50%)}

/* ── auth top bar ─────────────────────────────────────────────────────── */
.auth-home-brand{display:flex;align-items:center;color:var(--ink)}
.auth-home-brand img{display:block;width:68px;height:auto}
.auth-home-tools{display:flex;align-items:center;gap:8px}
.auth-home-tools .theme-switch{margin:0}
.auth-home-back{min-height:34px;display:flex;align-items:center;gap:6px;padding:0 12px;
  border-radius:var(--r);border:1px solid var(--line);background:var(--surface);color:var(--ink);font-size:13px;font-weight:500;text-decoration:none}
.auth-home-back:hover{background:var(--surface-2);color:var(--ink);text-decoration:none}
@media (max-width:560px){.auth-home-back span,.auth-home-back{display:none}}

/* ── intake / test-mode switches ────────────────────────────────────────── */
.switch-row{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap}
.switch-copy{min-width:0;flex:1 1 260px}
.switch-copy h3{margin:0 0 3px;font-size:14px;font-weight:600;color:var(--ink)}
.switch-state{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;font-size:12px;font-weight:500;padding:3px 10px;border-radius:99px;background:var(--surface-3);color:var(--ink-3)}
.switch-state:has(.switch-dot.on){background:var(--ok-soft);color:var(--ok-ink)}
.switch-state:has(.switch-dot.off){background:var(--bad-soft);color:var(--bad-ink)}
.switch-state:has(.switch-dot.warn){background:var(--warn-soft);color:var(--warn-ink)}
.switch-dot{width:6px;height:6px;border-radius:99px;flex:0 0 auto;background:currentColor}
.switch-dot.on{background:var(--ok)}
.switch-dot.off{background:var(--bad)}
.switch-dot.warn{background:var(--flag)}

.confirm{margin-top:12px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);padding:0}
.confirm[open]{border-color:var(--accent-line);background:var(--accent-soft)}
.confirm>summary{padding:10px 14px;min-height:40px;display:flex;align-items:center;border-radius:var(--r-md)}
.confirm-body{padding:0 14px 14px}
.confirm-body p{margin:0 0 10px}
.confirm-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
}

/* ── accounting dashboard ─────────────────────────────────────────────── */
.subtabs{display:flex;gap:4px;flex-wrap:wrap;align-items:flex-end;border-bottom:1px solid var(--line);margin:0 0 20px}
.subtabs a{position:relative;padding:8px 12px 12px;font-size:13.5px;font-weight:500;color:var(--ink-4);text-decoration:none;
  border-radius:var(--r-sm) var(--r-sm) 0 0;transition:color .14s var(--ease)}
.subtabs a:hover{color:var(--ink);text-decoration:none}
.subtabs a[aria-current='page']{color:var(--ink);font-weight:600}
.subtabs a[aria-current='page']::after{content:'';position:absolute;left:8px;right:8px;bottom:-1px;height:2px;border-radius:2px;background:var(--accent)}
@media (max-width:560px){.subtabs{gap:0;overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none}.subtabs::-webkit-scrollbar{display:none}.subtabs a{flex:0 0 auto;padding:8px 10px 12px}}

/* ── segmented control ──────────────────────────────────────────────────
   A sunken track holding one raised chip. Used where a page is a set of
   panels and exactly one is on screen: the choice and the current state are
   the same object, so it reads as a switch rather than as navigation. The
   underline .subtabs above stays for the accounting module, where the tabs
   are separate routes rather than panels of one page. */
.segbar{display:flex;gap:2px;flex-wrap:wrap;margin:0 0 20px;padding:3px;
  background:var(--surface-3);border:1px solid var(--line);border-radius:var(--r-md);
  width:fit-content;max-width:100%}
.segbar a{display:inline-flex;align-items:center;min-height:30px;padding:0 12px;
  border:1px solid transparent;border-radius:var(--r-sm);
  font-size:13px;font-weight:500;color:var(--ink-3);text-decoration:none;white-space:nowrap;
  transition:background .14s var(--ease),color .14s var(--ease)}
.segbar a:hover{color:var(--ink);text-decoration:none}
.segbar a[aria-current='page']{background:var(--surface);color:var(--ink);font-weight:600;
  border-color:var(--line);box-shadow:0 1px 2px rgba(16,24,40,.06)}
/* Narrow: one scrolling strip rather than a stack of half-empty rows. */
@media (max-width:720px){
  .segbar{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;width:100%;margin:0 0 14px;padding:2px}
  .segbar::-webkit-scrollbar{display:none}
  .segbar a{flex:1 1 auto;justify-content:center;min-height:28px;padding:0 8px;font-size:12.5px}
}

tr.rowlink{cursor:pointer;transition:background .12s var(--ease)}
tr.rowlink:hover{background:var(--surface-2)}
tr.rowlink a,tr.rowlink button{cursor:pointer}

.confirmedit{margin-top:20px;padding:14px 16px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2)}
.confirmedit label{margin:0 0 8px}
.confirmedit input{max-width:220px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}

.leadrow{padding:0;margin-bottom:10px;overflow:hidden}
.leadrow>summary{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;padding:14px 18px;cursor:pointer;list-style:none}
.leadrow>summary::-webkit-details-marker{display:none}
.leadrow>summary:hover{background:var(--surface-2)}
.leadrow[open]>summary{border-bottom:1px solid var(--line)}
.leadrow-main{display:flex;align-items:center;gap:9px;min-width:0}
.leadrow-main .nm{font-weight:600;font-size:14px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.leadrow-meta{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;font-size:12.5px;color:var(--ink-3);min-width:0}
.leadrow-meta time{color:var(--ink-4);white-space:nowrap}
.leadrow table{margin:0}
.leadrow .hint{padding:0 18px 15px}
.rowform{padding:0 18px 15px;margin:0}
.rowform button{font-size:13px;padding:7px 13px;min-height:34px}

td.rowacts,th.rowacts{text-align:right;white-space:nowrap;width:1%;padding-left:14px !important}
.rowacts-in{display:flex;gap:2px;justify-content:flex-end;align-items:center}
.rowact{display:inline-flex;align-items:center;gap:4px;padding:6px 8px;border-radius:var(--r-sm);
  border:0;background:none;cursor:pointer;color:var(--ink-3);font-size:12.5px;text-decoration:none;min-height:0;line-height:1;
  transition:background .13s var(--ease),color .13s var(--ease)}
.rowact:hover{background:var(--surface-3);color:var(--ink);text-decoration:none}
.rowact.is-dim{opacity:.45}
.rowact.is-dim:hover{opacity:1}
.rowact.is-danger:hover{background:var(--bad-soft);color:var(--bad-ink)}
.rowdel{display:inline-flex;margin:0}

/* A destructive header action, and its confirmation.
   The button itself is a plain .btnlink.ghostlink.iconbtn — same 40px box as
   every other header action, so the row aligns without special-casing; only
   the ink is red. Deleting a record is irreversible, so it is never one click:
   the <details> supplies the second step on a page that ships no JavaScript.
   Anchored under its own trigger rather than centred like popup(), because it
   belongs to the icon that opened it. */
/* A form wrapping a header action is plumbing, not layout: left as a block it
   is a zero-width flex child, which collapsed .actions to width 0 and wrapped
   every button onto its own line. It must not shrink either, or the label
   inside breaks over two lines and that button alone becomes 57px tall in a
   40px row. */
.actions form{margin:0;display:inline-flex;flex:none}
.actions .btnlink{white-space:nowrap}
.btnlink.ghostlink.is-danger{color:var(--bad-ink)}
.btnlink.ghostlink.is-danger:hover{background:var(--bad-soft);border-color:var(--bad-line)}
/* NOT .popup: that class sets display:contents, which removes the <details>
   box from layout entirely (0x0) and takes position:relative with it, so the
   panel below had nothing to anchor to. This carries its own box.
   The fixed height stops the closed element from reserving room for the panel
   it contains, which otherwise measured 70px in a 40px row. */
.headdel{position:relative;display:inline-flex;align-self:center;height:40px;flex:none}
.headdel>summary{list-style:none;cursor:pointer}
.headdel>summary::-webkit-details-marker{display:none}
.headdel[open]>summary{background:var(--bad-soft);border-color:var(--bad-line)}
.headdel>.dlg{position:absolute;top:calc(100% + 6px);right:0;z-index:60;
  width:max-content;max-width:280px;text-align:left;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow-lg)}
.headdel>.dlg .dlg-body{padding:14px}

/* The quarters and the years are ONE choice — which period am I looking at —
   so they share a single track with a hairline between the two groups, instead
   of sitting as two separate pills with a gap that read as two unrelated
   controls. The 4px gap is inside the track; the group is then pushed away
   from the primary action by .actions' own larger gap, so the CTA reads as a
   different KIND of thing rather than a third segment. */
.periodsel{display:inline-flex;gap:0;flex-wrap:wrap;align-items:center;
  padding:3px;border-radius:var(--r);background:var(--surface-3);
  border:1px solid var(--line)}
.periodsel .seg+.seg{margin-left:5px;padding-left:6px;
  border-left:1px solid var(--line-strong)}
.periodsel .seg{display:inline-flex;padding:0;border-radius:0;background:none;border:0;margin:0}
.periodsel a{display:inline-flex;align-items:center;justify-content:center;min-height:30px;padding:0 12px;border-radius:var(--r-sm);
  font-size:13px;font-weight:500;color:var(--ink-4);text-decoration:none;white-space:nowrap;transition:background .14s var(--ease),color .14s var(--ease)}
.periodsel a:hover{color:var(--ink);text-decoration:none}
.periodsel a[aria-current='true']{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(16,24,40,.08);font-weight:600}
@media (max-width:640px){.periodsel{width:100%}.periodsel .seg{flex:1 1 auto}.periodsel a{flex:1 1 auto}}

/* Three cards on ONE line: the trend takes the wide cell, the gauge and the
   category bars the two narrow ones. The chart only spans the full width once
   the row has dropped to two columns. */
.chartrow{display:grid;gap:16px;margin:0 0 16px;grid-template-columns:minmax(0,2.4fr) minmax(250px,.9fr) minmax(250px,.9fr)}
.chartrow>.card{margin:0;display:flex;flex-direction:column;gap:12px}
.chartrow h2{margin:0;font-size:15px}
.chart-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}
/* Day / month, in the chart's own header. Deliberately the SAME segmented
   track as the period chips upstairs (.periodsel): both answer "which slice of
   time", so a reader who has used one already knows this one. Slightly smaller,
   because it is a detail of the card rather than a choice about the page. */
.chart-grain{display:inline-flex;padding:2px;margin:0;border-radius:var(--r);
  background:var(--surface-3);border:1px solid var(--line)}
.chart-grain a{display:inline-flex;align-items:center;justify-content:center;min-height:26px;
  padding:0 10px;border-radius:var(--r-sm);font-size:12px;font-weight:500;color:var(--ink-4);
  text-decoration:none;white-space:nowrap;transition:background .14s var(--ease),color .14s var(--ease)}
.chart-grain a:hover{color:var(--ink);text-decoration:none}
.chart-grain a[aria-current='true']{background:var(--surface);color:var(--ink);
  box-shadow:0 1px 2px rgba(16,24,40,.08);font-weight:600}
/* Four series wrap onto two lines on a phone, so the swatch must stay glued to
   its own label — a bare gap let "Solde" and "TVA" break apart from the dot
   and read as two more series. */
.chart-head .legend{display:flex;align-items:center;flex-wrap:wrap;gap:2px 7px;
  margin:0;font-size:12px;color:var(--ink-4)}
.chart-head .legend .k{width:8px;height:8px;border-radius:99px;display:inline-block}
.chart-head .legend .k.income{background:var(--fin-income)}
.chart-head .legend .k.expense{background:var(--chart-expense)}
/* VAT is one series drawn in two colours — payable above the axis, reclaimable
   below — so its swatch is split rather than picking one and lying about the
   other half. */
.chart-head .legend .k.vat{background:var(--chart-vat)}
.chart-head .legend .k.net{background:var(--chart-net)}
.chart-head .legend .lg{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}

/* ---- monthly bars ---------------------------------------------------
   The chart is a positioning context for its tooltip, which is an absolutely
   positioned div rather than SVG text: it has to sit ON TOP of the bars with a
   background, and SVG has no z-order independent of document order. */
.mc{position:relative}
/* The SVG carries no height attribute, so the box is sized by the viewBox
   ratio and the card shrinks WITH the drawing. A min-height here would be
   actively wrong: preserveAspectRatio="meet" letterboxes the drawing inside
   whatever height it is given, so reserving 200px on a 293px-wide phone left
   80px of blank card above and below the bars.

   A max-height IS safe, because "meet" only letterboxes when the box is
   TALLER than the ratio needs — capping it just crops the slack. Without the
   cap a 700px-wide card produced a 361px chart that pushed the journal off
   the first screen. */
.mc svg{max-height:300px}
.mc-g{cursor:default}
/* ---- charts (piece E) -----------------------------------------------
   The months are now invisible hit slots over two continuous lines, not three
   bars each, so the old "dim every sibling" hover is gone with them: fading a
   line's own slots would strobe the ONE shape the card is about. Hover instead
   reveals that month's dashed crosshair and a marker on the live series —
   which is the reference's behaviour, and reads as pointing at the line rather
   than as dismissing everything else. */
.mc-cross,.mc-dot{transition:opacity .12s ease}
@media (hover:hover){
  .mc-g:hover .mc-cross{opacity:.5}
  .mc-g:hover .mc-dot{opacity:1}
}
.mc-g:focus{outline:none}
.mc-g:focus-visible .mc-cross{opacity:.5}
.mc-g:focus-visible .mc-dot{opacity:1}
/* Focus still needs a visible ring for keyboard users: the crosshair alone is
   a 1px dashed line and does not read as "this is where you are". */
.mc-g:focus-visible .mc-hit{fill:var(--accent-soft)}
/* The comparison key mirrors the dashed grey line it stands for. */
.chart-head .legend .k.expense{background:var(--chart-expense)}
/* ---- end charts (piece E) -------------------------------------------- */
.mc-tip{position:absolute;top:6px;z-index:2;pointer-events:none;
  min-width:150px;padding:9px 11px;border-radius:var(--r-sm,8px);
  border:1px solid var(--line);background:var(--surface-solid);
  box-shadow:0 6px 20px rgba(16,24,40,.13);font-size:12px;line-height:1.45}
.mc-tip[hidden]{display:none}
.mc-tip b{display:block;margin-bottom:5px;font-size:12.5px;color:var(--ink)}
.mc-tip dl{margin:0;display:grid;grid-template-columns:auto auto;gap:3px 12px}
.mc-tip dt{color:var(--ink-3);white-space:nowrap}
.mc-tip dd{margin:0;text-align:right;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.mc-tip .tip-note{margin:5px 0 0;font-size:11px;color:var(--ink-4)}
/* ── Category bars ──────────────────────────────────────────────────────
   A three-column grid — name / share / amount — with the track spanning all
   three underneath. Grid rather than flex so the percentages and the amounts
   form real columns down the card: as separate flex rows each line measured
   itself and the figures wandered left and right by a few pixels per row. */
.catlist{list-style:none;margin:0;padding:0;display:grid;gap:13px;min-width:0}
.catrow{display:grid;grid-template-columns:1fr auto auto;gap:2px 8px;align-items:baseline;min-width:0}
.cat-k{font-size:13px;color:var(--ink-2);min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* Tabular figures and a min-width so 5 % and 100 % occupy the same column. */
.cat-pct{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums;
  min-width:34px;text-align:right;white-space:nowrap}
.cat-v{font-size:12.5px;font-variant-numeric:tabular-nums;color:var(--ink);
  font-weight:500;white-space:nowrap}
.cat-track{grid-column:1/-1;height:7px;border-radius:99px;background:var(--chart-track);
  overflow:hidden;margin-top:4px}
.cat-fill{display:block;height:100%;border-radius:99px;background:var(--fin-expense)}

/* ── VAT card ───────────────────────────────────────────────────────────
   Figure, caption, then the two components as bars on a shared scale. The
   grid is label / amount / track so the three columns line up down the card
   rather than each row measuring itself. */
.vatcard{gap:0}
.vat-figure{margin:10px 0 0;font-size:30px;font-weight:600;line-height:1.05;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--ink)}
.vat-caption{margin:3px 0 0;font-size:12.5px;color:var(--ink-3)}
.vat-bars{margin-top:16px;display:grid;gap:12px}
.vat-row{display:grid;grid-template-columns:1fr auto;gap:2px 10px;align-items:baseline}
.vat-k{font-size:12.5px;color:var(--ink-3)}
.vat-v{font-size:12.5px;font-variant-numeric:tabular-nums;color:var(--ink);font-weight:500}
.vat-track{grid-column:1/-1;height:6px;border-radius:99px;background:var(--chart-track);
  overflow:hidden;margin-top:3px}
.vat-fill{display:block;height:100%;border-radius:99px}
/* Collected is money you owe on; deductible is money you get back. They are
   the two sides of the balance, so they take the two directions' hues. */
.vat-fill.is-collected{background:var(--fin-vat)}
.vat-fill.is-deductible{background:var(--fin-income)}

@media (max-width:1080px){.chartrow{grid-template-columns:1fr 1fr}.chart-main{grid-column:1/-1}}
@media (max-width:720px){.chartrow{grid-template-columns:1fr}}

.actionbar{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap;margin:0 0 14px}
.actionbar button{min-height:36px;display:inline-flex;align-items:center;gap:7px;padding:0 14px;font-size:13.5px}
.actionbar button.ghost{background:var(--surface);color:var(--ink);border:1px solid var(--line)}
.actionbar button.ghost:hover{background:var(--surface-2);color:var(--ink)}

/* ── forms and details ──────────────────────────────────────────────────
   The grammar shared by every form, detail and settings page. Lists and the
   dashboard own their own sections above; this one covers what happens when
   a card holds fields instead of data.

   Rules, in the DESIGN.md idiom: a card title row (15px semibold, optional
   grey link right) and never a naked heading; labels 13px/500 above a 40px
   input with a 12px grey hint below; short fields paired in a 2-column grid;
   exactly one primary button per card, right-aligned in a footer separated
   by a full-bleed hairline. Destructive actions are text-red secondaries,
   never a filled red button on a resting surface. */

/* Card title row. Detail and settings cards use .card-hd like the dashboard;
   these two rules give a bare h2 inside such a card the same metrics so a
   card that has no right-hand link still lines up with one that does. */
.card>h2,.card-hd h2{font-size:15px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
/* No icons in card titles: the title carries the meaning and a 17px glyph in
   front of every heading turned the page into a column of pictograms. */
.detail .card>h2>svg,.detail .card-hd h2>svg,
.formcard>h2>svg,.formcard .card-hd h2>svg{display:none}
/* The one-line grey subtitle under a card title. */
.card>h2+.sub,.card-hd+.sub{margin:-8px 0 16px;font-size:13px;color:var(--ink-4)}

/* Field grid: short fields sit two per row, long ones span. */
.frow{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.frow>div{min-width:0}
/* The grid owns the vertical rhythm, so the label's own top margin would
   double it. Every label in a field grid starts flush. */
.frow>div>label{margin-top:0}
.frow>div.is-wide{grid-column:1/-1}
/* First label in a card or a grid row does not need the 14px top margin that
   separates stacked fields. */
.frow>div>label:first-child,.card>form>label:first-child,
.card>h2+form>label:first-child{margin-top:0}
.field-hint{margin:6px 0 0;font-size:12.5px;color:var(--ink-4);line-height:1.55}

/* Card footer: a full-bleed hairline, then the actions right-aligned. The
   negative margin pulls the rule out to the card edge through its padding. */
.cardfoot{display:flex;align-items:center;justify-content:flex-end;gap:10px;flex-wrap:wrap;
  margin:20px -20px 0;padding:16px 20px 0;border-top:1px solid var(--line)}
.cardfoot>.spacer{margin-right:auto}
.cardfoot .hint{margin:0;flex:1 1 200px;text-align:left}
.cardfoot button,.cardfoot .btnlink{min-height:40px}
/* A destructive action reads as a red text button, not a filled red block. */
.cardfoot button.danger,.linkdanger{background:none;border:1px solid transparent;color:var(--bad-ink);
  font-weight:500;box-shadow:none}
.cardfoot button.danger:hover,.linkdanger:hover{background:var(--bad-soft);border-color:transparent;color:var(--bad-ink)}

/* Detail lead card: 40px initials tile, 18px name, one grey line, chip right. */
.leadcard{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.leadcard .lead-av{width:40px;height:40px;flex:0 0 auto;border-radius:var(--r-md);display:grid;
  place-items:center;background:var(--surface-3);color:var(--ink-3);
  font-size:14px;font-weight:600;letter-spacing:-.01em}
.leadcard .lead-av svg{width:19px;height:19px}
.leadcard .lead-copy{min-width:0;flex:1 1 240px}
.leadcard .lead-copy h2{margin:0;font-size:18px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.leadcard .lead-copy p{margin:2px 0 0;font-size:13px;color:var(--ink-4);overflow-wrap:anywhere}
.leadcard .lead-end{flex:0 0 auto;margin-left:auto;display:flex;align-items:center;gap:8px}

/* Fact list: a 2-column definition grid, 11px uppercase labels. */
.factlist{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:14px 28px;margin:16px 0 0}
.factlist>div:last-child:nth-child(n+3){flex:none}

/* Actions panel rows: label · control · 36px button. The outreach buttons at
   the top share the row rather than one filling it: a full-bleed blue bar was
   the loudest thing on a page whose subject is the person, not the button. */
.actpanel-row label{flex:0 0 68px}
.actpanel-top{gap:8px}
.actpanel-top .btnlink{flex:0 0 auto;min-height:40px;justify-content:center}
/* Two buttons share the row; one on its own stays its natural width rather
   than stretching into a blue bar the width of the panel. */
.actpanel-top .btnlink:not(:only-child){flex:1 1 0}

/* Timeline / feed / log nodes: 28px circles, hairline connectors. */
.tl li{padding-left:40px;margin-left:14px}
.tl .dot{left:-14px;width:28px;height:28px;font-size:11.5px}
.feed li{padding-left:40px;margin-left:14px}
.feed .fi{left:-14px;top:0;width:28px;height:28px;font-size:12px}
.tl .ph,.feed .fb,.log-line{font-size:13px}
.tl .dt,.feed .ft,.log-at{font-size:12px;color:var(--ink-4)}

/* Switch rows: one per setting, separated by a hairline, never boxed. */
.switch-row+.switch-row{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
.switch-copy p{margin:3px 0 0;font-size:13px;color:var(--ink-4);line-height:1.5}

/* Empty state inside a form/detail card: never taller than it must be. */
.card>.empty{padding:32px 24px}

/* ── popup ───────────────────────────────────────────────────────────── */
.popup{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px 16px;margin:0 0 14px}
.popup>.dlg>.dlg-head{position:static;padding:14px 0 10px;background:none}
.popup>.dlg>.dlg-body{padding:0}
.popup>.dlg .dlg-x{display:none}
.popup:not([open])>.dlg{display:none}
[data-js='on'] .popup{display:contents}
[data-js='on'] .popup>.popup-summary{display:none}
[data-js='on'] .popup:not([open])>.dlg{display:none}
[data-js='on'] .popup[open]>.dlg{display:block;padding:0;border:1px solid var(--line);
  border-radius:var(--r-lg);position:fixed;z-index:1000;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;
  max-width:min(760px,calc(100vw - 32px));width:100%;max-height:calc(100vh - 48px);overflow:auto;
  background:var(--surface-solid);box-shadow:var(--shadow-lg);color:var(--ink)}
[data-js='on'] .popup[open]>.dlg>.dlg-head{position:sticky;top:0;padding:16px 20px 12px;background:inherit}
[data-js='on'] .popup[open]>.dlg>.dlg-body{padding:16px 20px 20px}
[data-js='on'] .popup[open]>.dlg .dlg-x{display:inline-flex}
.dlg-scrim{position:fixed;inset:0;z-index:998;background:var(--scrim)}
html.has-dialog{overflow:hidden}
.dlg-head{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 20px 12px;background:inherit;border-bottom:1px solid var(--line)}
.dlg-head h2{margin:0;font-size:16px}
.dlg-x{background:none;border:0;padding:6px;border-radius:var(--r-sm);cursor:pointer;color:var(--ink-3);min-height:0;display:inline-flex}
.dlg-x:hover{background:var(--surface-3);color:var(--ink)}
.dlg-x svg{margin:0}
.dlg-body{padding:16px 20px 20px}
.dlg-body .toolbar{background:none;border:0;padding:0;margin:0}
.dlg-body .card{margin:0}
.dlg-body .row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.dlg-body .row>div{min-width:0}
.dlg-body label{margin-top:0}

/* ── drop zone ────────────────────────────────────────────────────────── */
.drop{margin-top:16px}
.drop input[type='file']{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.drop-face{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;text-align:center;padding:26px 20px;
  border:2px dashed var(--line-strong);border-radius:var(--r-md);background:var(--surface-2);color:var(--ink-3);cursor:pointer;
  transition:border-color .15s var(--ease),background .15s var(--ease),color .15s var(--ease)}
.drop-face>svg{color:var(--accent);margin:0}
.drop-face:hover{border-color:var(--accent);background:var(--accent-soft);color:var(--ink-2)}
.drop-face:active{background:var(--accent-soft);border-color:var(--accent)}
.drop input[type='file']:focus-visible+.drop-face{outline:2px solid var(--accent);outline-offset:2px}
.drop.is-over .drop-face{border-color:var(--accent);background:var(--accent-soft);color:var(--accent-ink)}
/* The middle line reads as the affordance: a pill button that reacts with the
   zone, so hovering anywhere in the dashed box lights the call to action. */
.drop-t{display:inline-flex;align-items:center;gap:8px;padding:9px 20px;font-size:14px;font-weight:600;
  border:2px solid var(--accent);border-radius:999px;background:var(--surface);color:var(--accent);
  transition:background .15s var(--ease),color .15s var(--ease)}
.drop-t>svg{margin:0}
.drop-face:hover .drop-t,.drop.is-over .drop-t{background:var(--accent);color:#fff}
.drop-s{font-size:12.5px;color:var(--accent-ink)}
.drop-list{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:6px}
.drop-list li{display:flex;align-items:center;gap:12px;font-size:12.5px;padding:8px 8px 8px 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface)}
.drop-list .nm{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drop-list .sz{flex:0 0 auto;color:var(--ink-4);font-variant-numeric:tabular-nums;white-space:nowrap}
.drop-x{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--r-sm);
  background:none;color:var(--ink-4);cursor:pointer;min-height:0;transition:background .13s var(--ease),color .13s var(--ease)}
.drop-x:hover{background:var(--bad-soft);color:var(--bad)}
.drop-x:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ── site cards / account rows ──────────────────────────────────────────── */
.crow.is-live{box-shadow:inset 3px 0 0 var(--ok)}
.crow.is-down{box-shadow:inset 3px 0 0 var(--bad)}
.clist.is-grid>.crow.is-live{box-shadow:none;border-color:var(--ok-line)}
.clist.is-grid>.crow.is-down{box-shadow:none;border-color:var(--bad-line)}
.crow.is-static{cursor:default}
.crow.is-static:hover{background:var(--surface)}
.clist.is-grid>.crow.is-static:hover{border-color:var(--line)}
.clist.is-grid>.crow.is-static.is-live:hover{border-color:var(--ok-line)}
.clist.is-grid>.crow.is-static.is-down:hover{border-color:var(--bad-line)}

.acc-sec+.acc-sec{margin-top:24px;padding-top:22px;border-top:1px solid var(--line)}
.acc-sec>h3{margin:0 0 12px;font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4)}
.acc-sec table{margin:0}
.acc-logins{list-style:none;margin:0;padding:0}
.acc-logins li{display:flex;align-items:center;gap:10px;min-height:36px;padding:4px 0;
  border-bottom:1px solid var(--line-soft);font-size:13px}
.acc-logins li:last-child{border-bottom:0}
.acc-logins .mono{font-weight:500;color:var(--ink)}
.acc-logins .muted{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acc-logins form{margin:0}
.acc-logins .pill{flex:0 0 auto}
.addr-input{display:flex;gap:6px;align-items:stretch}
.addr-input input{flex:1 1 auto;min-width:0}
.addr-input select{flex:0 0 auto;max-width:48%}
.acc-logins button{min-height:28px;padding:0 10px;font-size:12px}
/* Rarely-touched groups fold to one line; a refused submit opens theirs. */
.acc-more,.acc-fold{margin-top:14px}
.acc-more>summary,.acc-fold>summary{list-style:none;color:var(--ink-2)}
.acc-more>summary::-webkit-details-marker,.acc-fold>summary::-webkit-details-marker{display:none}
.acc-more>summary::before,.acc-fold>summary::before{content:'›';font-size:16px;line-height:1;
  color:var(--ink-4);transition:transform .15s var(--ease)}
.acc-more[open]>summary::before,.acc-fold[open]>summary::before{transform:rotate(90deg)}
.acc-more[open]>summary,.acc-fold[open]>summary{margin-bottom:8px;color:var(--ink)}

.checkline{display:flex;gap:8px;align-items:center;margin-top:16px;color:var(--ink-2)}
.checkline input[type='checkbox'],.checkline input[type='radio']{width:auto;flex:0 0 auto;margin:0;min-height:0;accent-color:var(--accent)}
.checkline input[type='radio']{width:16px;height:16px}

/* ── copy buttons ───────────────────────────────────────────────────────── */
.copybtn{display:inline-flex;align-items:center;gap:7px}
.copybtn svg{margin-left:0;vertical-align:-2px}
.copybtn.is-copied{background:var(--ok-soft);border-color:transparent;color:var(--ok-ink)}
.copybtn.is-copied:hover{background:var(--ok-soft);border-color:transparent;color:var(--ok-ink)}
.copyrow{display:flex;gap:8px;flex-wrap:wrap}
.iconbtn{width:40px;padding:0;justify-content:center}
.iconbtn svg{margin:0}

/* ── dashboard insights ─────────────────────────────────────────────────── */
.deadline-card{margin-bottom:16px}
.deadline-card .card-hd h2{display:flex;align-items:center;gap:8px;font-size:15px}
.deadline-list{list-style:none;margin:0;padding:0;display:grid;gap:0;border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden}
.deadline{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;
  padding:10px 14px;border:0;border-bottom:1px solid var(--line-soft);border-radius:0;background:var(--surface)}
.deadline:last-child{border-bottom:0}
.deadline-when{font-size:12px;font-weight:500;padding:3px 10px;border-radius:99px;white-space:nowrap;
  background:var(--surface-3);border:0;color:var(--ink-3)}
.deadline-what{font-size:13.5px;color:var(--ink-2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.deadline-date{font-family:inherit;font-size:12.5px;color:var(--ink-4);white-space:nowrap;font-variant-numeric:tabular-nums}
.deadline.is-soon{background:var(--surface)}
.deadline.is-soon .deadline-when{background:var(--warn-soft);color:var(--warn-ink)}
.deadline.is-late{background:var(--surface)}
.deadline.is-late .deadline-when{background:var(--bad-soft);color:var(--bad-ink)}
@media (max-width:560px){.deadline{grid-template-columns:auto 1fr;row-gap:6px}.deadline-date{grid-column:2;justify-self:start}}

.spark-wrap{flex:1;min-height:120px;display:flex;align-items:stretch}
/* ---- charts (piece E): spark scale ----------------------------------
   The bars used to be the whole chart, which made them a shape rather than a
   quantity. The scale column is a flex sibling holding the max and the floor
   hard against the plot's own top and bottom edges, so the two labels line up
   with the bars they bound instead of floating near them. */
.spark-bars{width:100%;height:120px;display:flex;align-items:stretch;gap:8px;padding-top:8px;box-sizing:border-box}
.spark-bars .sb-plot{flex:1 1 auto;min-width:0;display:flex;align-items:flex-end;gap:4px}
.spark-bars .sb-scale{flex:0 0 auto;display:flex;flex-direction:column;
  justify-content:space-between;align-items:flex-end;
  font-size:12px;color:var(--chart-axis);font-variant-numeric:tabular-nums}
.spark-bars .sb-scale b{font-weight:400;line-height:1;
  /* Nudge the two labels onto the lines they mark rather than beside them:
     the top sits on the ceiling, the bottom on the baseline. */
  transform:translateY(-.35em)}
.spark-bars .sb-scale b:last-child{transform:translateY(.35em)}
/* ---- end charts (piece E) -------------------------------------------- */
.spark-bars .sb{flex:1 1 0;min-width:2px;border-radius:4px 4px 2px 2px;background:var(--blue-soft);position:relative;transition:background .15s var(--ease)}
.spark-bars .sb:hover{background:var(--blue-line)}
.spark-bars .sb.is-peak{background:var(--accent)}
/* The peak's printed figure is gone with its data-v: the scale column now
   states the maximum once, and having both made the same number look like two
   readings. The bar keeps its accent fill, which is what marks it. */

.ranklist{list-style:none;margin:0;padding:0;display:grid;gap:11px;min-width:0}
.ranklist>li{min-width:0}
.chartrow>.card,.chartrow>section{min-width:0;overflow:hidden}
.rank-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:5px;min-width:0}
.rank-label{font-size:13px;color:var(--ink-2);min-width:0;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-n{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:12.5px;color:var(--ink);white-space:nowrap;font-variant-numeric:tabular-nums;flex:0 0 auto;display:inline-flex;gap:8px;align-items:baseline}
.rank-pct{color:var(--ink-4);font-size:11.5px}
.ranklist>li:hover .rank-track>span{background:var(--accent-ink,var(--accent))}
.ranklist>li:hover .rank-label{color:var(--ink)}
.rank-track{height:4px;border-radius:99px;background:var(--line-soft);overflow:hidden;max-width:220px}
.rank-track>span{display:block;height:100%;border-radius:99px;background:var(--accent)}

/* ── contacts (CRM area) ────────────────────────────────────────────────── */
.chipmore{display:contents}
.chipmore>summary{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:500;
  min-height:32px;padding:0 12px;border-radius:var(--r);border:1px dashed var(--line-strong);
  background:var(--surface);color:var(--ink-3);cursor:pointer;list-style:none;user-select:none}
.chipmore>summary::-webkit-details-marker{display:none}
.chipmore>summary:hover{border-color:var(--ink-4);color:var(--ink)}
.chipmore>summary .less{display:none}
.chipmore[open]>summary .more{display:none}
.chipmore[open]>summary .less{display:inline}
.crow .bulk-pick{position:relative;z-index:2;width:16px;height:16px;margin:0;flex:0 0 auto;min-height:0;accent-color:var(--accent);cursor:pointer}
.bulkbar{display:none;flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;
  padding:8px 8px 8px 14px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.clist:has(.bulk-pick:checked)~.bulkbar{display:flex}
@supports not selector(:has(a)){.bulkbar{display:flex}}
.bulkbar .bulk-lbl{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:600;color:var(--ink-2);margin-right:4px}
.bulkbar .bulk-ic{width:20px;height:20px;border-radius:50%;display:grid;place-items:center;background:var(--accent);color:#fff}
.bulkbar .bulk-del{display:inline-flex;align-items:center;gap:6px;margin-left:auto}
.bulkbar input{width:132px;min-height:34px;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase}
.bulkbar button{min-height:34px;padding:0 14px;font-size:13px}
.list-foot{margin-top:14px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.foot-go{display:inline-flex;align-items:center;gap:4px;font-size:12.5px;font-weight:500;color:var(--link);text-decoration:none}
.foot-go:hover{text-decoration:underline}

.banner-impersonate{display:flex;justify-content:space-between;align-items:center;gap:14px;
  margin:0 0 16px;padding:4px 6px 4px 12px;min-height:32px;border-radius:var(--r);font-size:12.5px;font-weight:400;
  border:0;background:var(--notice-bg);color:var(--ink-2)}
.banner-impersonate strong{font-weight:600;color:var(--ink)}
.banner-impersonate .btnlink{background:transparent;color:var(--ink);border-color:transparent;font-weight:600;
  min-height:28px;padding:0 8px;text-decoration:underline;text-underline-offset:3px}
.banner-impersonate .btnlink:hover{background:rgba(0,0,0,.05);color:var(--ink)}

/* Sidebar workspace chooser (platform). Lives inside the workspace card. */
.side-pick{margin:0;cursor:default}
.side-pick .side-ws-copy,.side-pick .side-user-copy{flex:1 1 auto;gap:2px}
.side-pick-row{display:flex;align-items:center;gap:4px;min-width:0}
.side-pick-row>select,.side-pick-row>.cs{flex:1 1 auto;min-width:0;margin:0}
.side-pick-row>select,.side-pick-row .cs-btn{min-height:26px;padding:2px 24px 2px 0;font-size:13px;font-weight:600;
  border:0;background-color:transparent;border-radius:var(--r-sm);background-position:right 4px center;box-shadow:none}
.side-pick-row>select:focus,.side-pick-row .cs-btn:focus-visible{box-shadow:0 0 0 2px var(--accent-soft)}
.side-pick-row .cs-btn{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;position:relative;padding-right:4px}
.side-pick-row .cs-btn>span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side-pick-row .cs-btn svg{display:none}
.side-pick-row>select{background-image:none;padding-right:0}
.side-pick-row .cs-btn[aria-expanded="true"] svg{transform:translateY(-50%) rotate(180deg)}
.side-pick-go{flex:0 0 auto;width:26px;min-height:26px;margin:0;padding:0;display:grid;
  place-items:center;border-radius:var(--r-sm);background:transparent;border:0;color:var(--ink-4)}
.side-pick-go:hover{background:var(--surface-3);color:var(--ink)}
.side-pick-go svg{width:14px;height:14px;margin:0}

/* With script running the select submits itself; the arrow is the no-JS path. */
[data-js='on'] .side-pick-go{display:none}
.canvas[inert]{pointer-events:none;user-select:none}

.auth-more{margin-top:12px}
.auth-more form{margin-top:12px}
.auth-more form>div{margin-top:12px}

@media (max-width:560px){
  .subtabs{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent)}
}

/* ── dashboard (portail/index.ts) ─────────────────────────────────────────
   Every section is ONE card: a header row (title left, grey "See all" right),
   then its content. KPIs are hairline-separated cells inside the card, not
   four bordered tiles on the canvas; the count pills live in a grey summary
   strip at the top of the performance card. 16px between cards, 20px card
   padding, 12px cell padding — no other gaps. */
.dash-card{margin-bottom:16px}
.dash-card>.card-hd{margin:0 0 12px}
.dash-card .card-hd .eyebrow{display:none}
.dash-card .card-hd h2{font-size:15px;font-weight:600;color:var(--ink);margin:0}
.dash-card .card-hd>a{display:inline-flex;align-items:center;gap:4px;font-size:13px;font-weight:500;color:var(--ink-4);white-space:nowrap}
.dash-card .card-hd>a:hover{color:var(--ink);text-decoration:none}
.dash-card .card-hd>a svg{width:14px;height:14px}

/* Summary strip: full-bleed grey band at the top of the card, top corners
   rounded with the card. An icon tile, then the pills; nothing else. */
.dash-strip{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  margin:0 -20px;padding:10px 20px;background:var(--surface-2);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.dash-strip-left{display:inline-flex;align-items:center;gap:12px;min-width:0}
.dash-strip-label{font-size:14px;font-weight:500;color:var(--ink);white-space:nowrap}
.dash-strip .metrics{margin:0 0 0 auto;gap:8px;justify-content:flex-end}
.dash-strip .metric.warn .n{color:var(--ink)}

/* KPI cells: no per-tile border; 1px hairlines between cells (and between
   rows when they wrap) come from the 1px gap over the line colour. The row
   bleeds 8px into the card padding so the first label lines up with the
   card title at 20px. */
.stats.is-inset{gap:1px;margin:0 -8px;background:#f1f3f7;background:var(--line-soft);border-radius:0;
  grid-template-columns:repeat(auto-fit,minmax(176px,1fr))}
.stats.is-inset>.stat{border:0;border-radius:0;padding:12px 8px;background:var(--surface)}
.stats.is-inset>.stat:hover{background:var(--surface-2);border-color:transparent}
.stats.is-inset>.stat:not(:first-child){padding-left:12px}
.stats.is-inset>.stat .n{font-size:22px;line-height:1.15}
.stats.is-inset>.stat .l{margin-bottom:10px;justify-content:flex-start;gap:8px}
.stats.is-inset>.stat .f{margin-top:5px}
.stats.is-inset>.stat .stat-icon{order:-1;width:16px;height:16px;border:0;border-radius:0;
  background:transparent;color:var(--ink-4)}
.stats.is-inset>.stat.accent .stat-icon{background:transparent;color:var(--accent)}
.stats.is-inset>.stat.warn .stat-icon{background:transparent;color:var(--bad)}
.stats.is-inset>.stat.good .stat-icon{background:transparent;color:var(--ok)}
/* A card whose whole content is the KPI strip: the tiles run to the card's
   own edges rather than sitting in a second, inset box. Opt-in, not inferred
   from :only-child — the accounting KPI card is also an inset strip alone in
   a card, and it needs its own padding and its category bars unclipped. */
.stats-flush>.stats.is-inset{margin:-20px;width:auto;border-radius:var(--r-lg);overflow:hidden}
.stats-flush>.stats.is-inset>.stat{padding:16px 20px}

/* The one-line verdict badge that opens a result card. */
.verdict{margin:0 0 10px}

/* Deadline rows inside the card: hairline-separated, no inner box. */
.dash-card .deadline-list{border:0;border-radius:0;margin:-8px -20px -20px}
.dash-card .deadline{padding:0 20px;min-height:52px;grid-template-columns:auto 1fr auto;gap:12px}
.dash-card .deadline:last-child{border-bottom:0}
.dash-card .deadline-what{font-size:14px;font-weight:500;color:var(--ink)}
.deadline-right{display:inline-flex;align-items:center;gap:12px;justify-self:end}
.row-tile{width:28px;height:28px;border-radius:var(--r-sm)}
.row-tile svg{width:14px;height:14px}

/* Project rows inside the card: the list IS the card body. */
.dash-list{border:0;border-radius:0;background:transparent;margin:0 -20px -20px}
.dash-list>.crow{padding:10px 20px;min-height:52px;gap:12px;flex-wrap:nowrap;align-items:center}
.dash-list>.crow>.row-tile{flex:0 0 auto}
.dash-list>.crow>.crow-body{flex:1 1 auto;min-width:0}
.dash-list>.crow>.right{flex:0 0 auto;gap:8px}
.dash-list>.crow .row-go{margin-left:4px;background:var(--surface-3);color:var(--ink-4)}
.dash-list>.crow:hover .row-go{background:var(--line);color:var(--ink)}
.dash-list>.crow:last-child{border-bottom:0;border-radius:0 0 calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px)}

/* Charts inside the traffic card: three panes separated by hairlines, not
   three more cards. */
.dash-card .chartrow{margin:16px 0 0;padding-top:16px;border-top:1px solid var(--line-soft);gap:0 24px}
.dash-card .chartrow>.card{border:0;border-radius:0;padding:0;margin:0;background:transparent}
.dash-card .chartrow>.chart-side{border-top:1px solid var(--line-soft);padding-top:16px;margin-top:16px}
.dash-card .chartrow>.chart-side+.chart-side{border-left:1px solid var(--line-soft);padding-left:24px}
.dash-card .chartrow h2,.dash-card .dash-sub h2{font-size:14px;color:var(--ink)}
.dash-card .dash-sub{border:0;border-radius:0;padding:16px 0 0;margin:16px 0 0;border-top:1px solid var(--line-soft)}
.dash-card .spark-bars .sb{background:var(--blue-soft)}
.dash-card .spark-bars .sb.is-peak{background:var(--accent)}

/* Empty state inside a section card: icon tile, one sentence, one link. */
.dash-empty{padding:12px 20px 12px;color:var(--ink-3)}
.dash-empty .ei{background:var(--surface-3);border:0;width:40px;height:40px;border-radius:50%;
  box-shadow:0 0 0 4px var(--surface-2);margin-bottom:14px}
.dash-empty-title{font-size:14px;font-weight:500;color:var(--ink);margin:0 0 4px}
.dash-empty .muted{font-size:13px;max-width:520px;margin:0 auto}
.dash-empty-link{margin:14px 0 0}
.dash-empty-link a{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:500;color:var(--ink);min-height:36px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface);text-decoration:none}
.dash-empty-link a:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink);text-decoration:none}
.dash-note a{color:var(--ink-3)}
.dash-note a:hover{color:var(--ink)}
.dash-empty-link .hint{margin-top:8px}

.dash-status>.card-hd{margin:0 0 4px}
.dash-status-right{display:flex;align-items:center;gap:12px;flex:0 0 auto}
.dash-status .sub{margin:0}
.dash-note{margin:12px -20px -8px;padding:12px 20px 0;border-top:1px solid var(--line-soft);font-size:13px;color:var(--ink-4)}
.dash-note a{display:inline-flex;align-items:center;gap:4px;margin-left:4px}
.dash-card+.support-note{margin-top:24px}

@media (max-width:1080px){
  .dash-card .chartrow>.chart-side+.chart-side{border-left:1px solid var(--line-soft);padding-left:24px}
}
@media (max-width:720px){
  .dash-card .chartrow>.chart-side+.chart-side{border-left:0;padding-left:0}
}
@media (max-width:640px){
  .dash-strip{margin:0 -16px;padding:10px 16px}
  .dash-status>.card-hd{flex-wrap:wrap}
  .stats.is-inset{gap:1px;margin:0 -4px}
  .stats.is-inset>.stat{padding:12px 4px 12px 8px}
  .dash-list{margin:0 -16px -16px}
  .dash-card .deadline-list{margin:-8px -16px -16px}
  .dash-card .deadline{padding:0 16px;grid-template-columns:auto 1fr;row-gap:4px;min-height:0;padding-block:10px}
  .dash-card .deadline-right{grid-column:2;justify-self:start}
  .dash-list>.crow{padding:12px 16px}
}

/* project row: the trailing arrow is a bare glyph, not a control */
.dash-list .row-go{border:0;background:transparent;width:20px;height:20px;color:var(--ink-5)}
.dash-list .crow:hover .row-go{background:transparent;color:var(--ink)}
/* ── lists and tables ─────────────────────────────────────────────────────
   Every list page is ONE bordered card: a grey summary strip on top (icon
   tile + "Total : N" on the left, search / filter / sort / the page action
   on the right), an optional 12px grey header row, then 52px rows separated
   by hairlines. The vocabulary is the dashboard's — .dash-strip, .dash-list,
   .itile.row-tile, .dash-empty — and .lcard only drops the card padding so
   the bands run edge to edge. Columns (.lc-*) give the status pill and the
   date a fixed slot so rows line up like a table without being one. */
.lcard{padding:0;overflow:visible}
.lcard>.dash-strip{margin:0;border-top:0;min-height:52px;padding:8px 20px 7px;gap:12px;position:relative;
  border-radius:calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0}
.lcard>.lfoot{border-radius:0 0 calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px)}
.pill.lstrip-note{background:var(--surface-3);color:var(--ink-3)}
.lstrip-right button.ghost{min-height:36px}
.lstrip-note{font-size:13px;color:var(--ink-3)}
form.lstrip-right{margin:0}
.lstrip-right select,.lstrip-right .cs-btn{min-height:36px;width:auto;min-width:0;font-size:13px;padding-block:6px}
.lstrip-right .cs{width:auto;flex:0 0 auto}
.lcard>.dash-list{margin:0;border-radius:0}
.lcard>.dash-list>.crow{padding:8px 20px;min-height:52px;gap:12px}
.lcard>.dash-list>.crow>.right{gap:12px}
.lcard .crow.is-overdue,.lcard .crow.is-live,.lcard .crow.is-down{box-shadow:none}
.lcard .crow.is-static{cursor:default}
.dash-strip-left .itile{width:28px;height:28px;border-radius:var(--r-sm)}
.dash-strip-left .itile svg{width:14px;height:14px}
.dash-strip-left .dash-strip-label b{font-weight:600}
.dash-strip .metrics{flex-wrap:wrap}
.lstrip-right{display:flex;align-items:center;gap:8px;margin-left:auto;flex-wrap:wrap}
.lstrip-right .metrics{margin:0}

/* Strip controls: a 36px white bordered search, 32px secondary buttons, the
   one primary button of the page at the same height. */
.lsearch{position:relative;display:inline-flex;align-items:center;margin:0}
.lsearch>svg{position:absolute;left:11px;width:14px;height:14px;color:var(--ink-4);pointer-events:none}
.lsearch input{min-height:36px;width:280px;padding:6px 12px 6px 32px;font-size:13px}
.lstrip-right .row-action,.lstrip-right button.ghost,.lstrip-right .btnlink.ghostlink{min-height:32px;padding:0 12px;font-size:13px;font-weight:500;
  display:inline-flex;align-items:center;gap:6px}
.lstrip-right button.primary,.lstrip-right .btnlink:not(.ghostlink){min-height:32px;padding:0 12px;font-size:13px;font-weight:500;
  display:inline-flex;align-items:center;gap:6px}
.lstrip-right button svg,.lstrip-right .btnlink svg{margin:0;width:14px;height:14px;vertical-align:0}
.lstrip-right form{display:inline-flex;margin:0}
.lstrip-right .chips{margin:0;gap:4px}
.lstrip-right .chips a{min-height:28px;padding:0 10px;font-size:12.5px;border-color:transparent;background:transparent;color:var(--ink-3)}
.lstrip-right .chips a:hover{background:var(--surface);border-color:var(--line)}
.lstrip-right .chips a[aria-current='true']{background:var(--surface);border-color:var(--line);color:var(--ink);font-weight:600}
.lstrip-right .chips a .c{opacity:.6}

/* Header row: 12px medium grey on the muted surface, never uppercase. */
.lhead{display:flex;align-items:center;gap:12px;min-height:36px;padding:0 20px;
  background:var(--surface-2);border-bottom:1px solid var(--line);
  font-size:12px;font-weight:500;color:var(--ink-3)}
.lhead>span{flex:0 0 auto;white-space:nowrap}
.lhead .lc-name{flex:1 1 auto;min-width:0}

/* Column slots, shared by the header and the rows. */
.lc-pick,.lc-lead{width:28px;flex:0 0 auto}
.lc-status{width:120px;flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.lc-date{width:176px;flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;
  font-size:12px;color:var(--ink-4);white-space:nowrap;font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis}
.lc-date>svg{width:14px;height:14px;color:var(--ink-5);flex:0 0 auto}
.lc-date.is-bad{color:var(--bad-ink)}
.lc-date.is-bad>svg{color:var(--bad)}
.lc-acts{width:28px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:8px}
.lc-acts.is-2{width:64px}
/* KRUZ's own row carries its role tag where a client row carries nothing:
   fixed width so the kebabs stay in one column down the list. */
.lc-role{width:104px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end}

/* Rows: 28px leading tile or avatar, two-line stack, quiet 28px targets. */
.lcard .crow .bulk-pick{width:16px;height:16px;margin:6px;flex:0 0 auto}
.lcard .crow>.av-sm,.lcard .crow>.itile{flex:0 0 auto}
.lcard .crow .star{width:28px;height:28px;font-size:14px;color:var(--ink-4)}
.lcard .crow .star:hover{color:var(--ink)}
button.row-go{border:0;background:none;padding:0;min-height:0;cursor:pointer;font:inherit;display:grid;place-items:center;position:relative;z-index:2}
button.row-go svg{margin:0}
button.row-go:hover{background:transparent;color:var(--ink)}
.lcard .crow .row-go svg{width:16px;height:16px}
.lcard .crow .meta .muted{color:var(--ink-4);font-size:12px}
.taglist.is-inline{display:inline-flex;margin:0;gap:4px}
.taglist.is-inline a.tagchip{font-size:11.5px;padding:2px 8px}
.lc-status .pill{font-size:11.5px;padding:2px 8px}
.lcard .crow .row-go{width:28px;height:28px;background:transparent;color:var(--ink-5)}
.lcard .crow:hover .row-go{background:transparent;color:var(--ink)}
a.row-go{text-decoration:none;position:relative;z-index:2}
a.row-go:hover{color:var(--ink);text-decoration:none}
.lcard .crow .nm{font-size:14px;line-height:1.3}
.lcard .crow .who{line-height:1.3}
.lcard .crow .meta{gap:10px;margin-top:1px;line-height:1.3}
.lc-date.is-ok{color:var(--ok-ink)}
.lc-date.is-ok>svg{color:var(--ok)}
.lhead .lc-acts{width:auto;min-width:28px;justify-content:flex-end}
.lhead .bulk-pick{width:16px;height:16px;margin:6px;min-height:0;opacity:.45}
/* Row menu: one quiet 28px kebab, a floating white menu of the row's actions. */
.rowmenu{position:relative;display:inline-flex;margin:0;padding:0;border:0;background:none}
.rowmenu>summary{list-style:none;width:28px;height:28px;display:grid;place-items:center;border-radius:var(--r-sm);
  color:var(--ink-4);cursor:pointer;user-select:none;transition:background .13s var(--ease),color .13s var(--ease)}
.rowmenu>summary::marker,.rowmenu>summary::-webkit-details-marker{display:none;content:''}
.rowmenu>summary::after{content:none}
.rowmenu>summary:hover,.rowmenu[open]>summary{background:var(--surface-3);color:var(--ink)}
.rowmenu>summary svg{width:16px;height:16px}
.rowmenu-panel{position:absolute;right:0;top:32px;min-width:184px;z-index:30;display:flex;flex-direction:column;gap:1px;
  padding:4px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:0 8px 24px rgba(16,24,40,.08)}
.rowmenu-panel a,.rowmenu-panel button{display:flex;align-items:center;gap:8px;width:100%;min-height:32px;padding:0 10px;margin:0;
  border:0;border-radius:var(--r-sm);background:none;color:var(--ink);font:inherit;font-size:13px;font-weight:500;
  text-align:left;text-decoration:none;cursor:pointer;white-space:nowrap}
.rowmenu-panel a:hover,.rowmenu-panel button:hover{background:var(--surface-2);color:var(--ink);text-decoration:none}
.rowmenu-panel form{margin:0;display:block}
.rowmenu-panel button svg{margin:0}
.crow .rowmenu{z-index:3}
/* A row with its menu open outranks the rows after it. Without this the
   panel is painted under the next row, which has its own stacking context
   from .crow{position:relative}, and the two texts overlap. */
.crow:has(.rowmenu[open]){z-index:40}
/* The row already shows it is active by holding the open menu; its focus
   ring would otherwise be drawn across the panel. */
.crow:has(.rowmenu[open]):focus-within{outline:none}
.crow:has(.rowmenu[open]){background:var(--surface-2)}
.clist:has(.rowmenu[open]){position:relative;z-index:40}
/* The list clips its children so the row hairlines follow the card's rounded
   corners. On the LAST row the menu opens past the bottom edge, so the clip
   has to be lifted while a menu is open — otherwise the panel is cut off
   rather than merely overlapped. */
.clist:has(.rowmenu[open]),.lcard:has(.rowmenu[open]){overflow:visible}
.lcard:has(.rowmenu[open]),.card:has(.rowmenu[open]){position:relative;z-index:40}
.lcard:has(.rowmenu[open]) .lfoot{position:relative;z-index:0}
@supports not selector(:has(a)){.rowmenu-panel{background:var(--surface-solid)}}
/* A menu that holds a form, not just links: the private demos set a password
   from the same kebab every other list uses for its row actions. */
.rowmenu-panel .menuform{display:flex;flex-direction:column;gap:6px;padding:6px 6px 4px;min-width:224px}
.rowmenu-panel .menuform label{font-size:11.5px;font-weight:500;color:var(--ink-4);margin:0}
.rowmenu-panel .menuform input{width:100%;min-height:34px}
/* The panel greys its buttons flat, which is right for menu items and wrong
   for the form's submit — that one is the panel's action. */
.rowmenu-panel .menuform button{justify-content:center;min-height:34px;
  background:var(--accent);color:#fff;font-weight:500}
.rowmenu-panel .menuform button:hover{background:var(--accent-hover);color:#fff}
/* The kebab's card: the address, the recoverable password and its copy button,
   the update date and the form — everything about the row, one click away, so
   the row itself carries only a name and a state. */
.menucard{display:flex;flex-direction:column;gap:6px;padding:8px 8px 4px;min-width:250px}
.menucard-path{margin:0;font-size:12px;color:var(--ink-4);overflow-wrap:anywhere}
.menucard-pw{margin:0;font-size:13px;font-weight:500;color:var(--ink);overflow-wrap:anywhere}
.menucard-note{margin:0;font-size:12px;color:var(--ink-4);white-space:normal;line-height:1.45}
/* The panel flattens its buttons; the copy button has to read as a control
   again or it looks like a stray line of text under the password. */
.rowmenu-panel .menucard .copybtn{justify-content:center;min-height:30px;font-size:12.5px;
  background:var(--surface);border:1px solid var(--line);color:var(--ink)}
.rowmenu-panel .menucard .copybtn:hover{background:var(--surface-2);border-color:var(--line-strong)}
.rowmenu-panel .menucard .menuform{padding:6px 0 0;min-width:0;border-top:1px solid var(--line-soft)}
/* The avatar keeps its own flex:0 0 auto, so the body has to be told to grow
   or the row's actions stop short of the card's right edge. */
.demo-list>.crow>.crow-body{flex:1 1 auto;min-width:0}
.lcard .crow .msg{-webkit-line-clamp:1;line-clamp:1;margin-top:4px;font-size:12.5px}
.lcard .crow .taglist{margin:6px 0 0}
.lcard .crow .who .pill{font-size:11.5px;padding:2px 8px}
.lcard .crow .row-action{min-height:28px;padding:0 10px;font-size:12.5px}
.itile.row-tile.is-up{background:var(--ok-soft);border-color:transparent;color:var(--ok-ink)}
.itile.row-tile.is-down{background:var(--bad-soft);border-color:transparent;color:var(--bad-ink)}
.itile.row-tile.is-wait{background:var(--surface-3);border-color:transparent;color:var(--ink-4)}

/* Missing-state pill (no login, no address): the warning pair. */
.badge.warn,.pill.warn{background:var(--warn-soft);color:var(--warn-ink)}

/* Footer band: pager on the left, "n in this view" on the right. */
.lfoot{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  padding:10px 20px;border-top:1px solid var(--line-soft);font-size:12.5px;color:var(--ink-4);min-height:44px}
.lfoot .pager{margin:0}
.lfoot .list-foot{margin:0}
.lcard>.bulkbar{margin:0;border:0;border-top:1px solid var(--line);border-radius:0;padding:8px 20px;background:var(--surface-2)}

.chart-side .dash-empty,.chart-main .dash-empty{padding:24px 0}
.chart-main .dash-empty{flex:1 1 auto;display:flex;flex-direction:column;justify-content:center}
.lcard .lfoot .foot-go{color:var(--ink-3)}

/* Empty state inside the list card: dashboard anatomy, 32px of air. */
.lcard>.dash-empty{padding:32px 20px}
.lcard>.dash-empty .dash-empty-title{font-weight:600}

/* Contacts: the <details> filter is the strip. Its summary is the Filter
   button in the strip; its body drops down under the strip, on the muted
   surface, over the first rows. No script: the disclosure is native. */
.lcard .fbar{margin:0;border:0;border-radius:0;overflow:visible;background:transparent;display:inline-flex;position:static}
.lcard .fbar>summary{display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 10px 0 12px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--surface);color:var(--ink);
  font-size:13px;font-weight:500;white-space:nowrap;cursor:pointer;list-style:none;user-select:none}
.lcard .fbar>summary::marker,.lcard .fbar>summary::-webkit-details-marker{content:'';display:none}
.lcard .fbar>summary::after{content:none}
.lcard .fbar>summary:hover{background:var(--surface-2);border-color:var(--line-strong);color:var(--ink)}
.lcard .fbar[open]>summary{background:var(--surface-3);border-color:var(--line-strong)}
.fbar-btn>svg,.lcard .fbar>summary .fbar-ic svg{width:14px;height:14px;color:var(--ink-3)}
.lcard .fbar>summary .fbar-chev{width:auto;height:auto;border:0;background:none;color:var(--ink-4)}
.lcard .fbar-cur{font-size:13px;color:var(--ink-3);font-weight:500}
.lcard .fbar-body{position:absolute;left:0;right:0;top:100%;z-index:6;display:flex;flex-direction:column;gap:12px;
  background:var(--surface-2);border-bottom:1px solid var(--line);padding:12px 20px 14px;box-shadow:0 8px 24px rgba(16,24,40,.08)}
.lcard .fbar-body .chips a{background:var(--surface);border-color:var(--line);color:var(--ink-3);min-height:28px;font-size:12.5px}
.lcard .fbar-body .chips a[aria-current='true']{background:var(--surface);border-color:var(--ink-4);color:var(--ink);font-weight:600}
.lcard .fbar-body .chips a[aria-current='true'] .c{color:var(--ink-3)}
.lcard .fbar-body .chipmore>summary{background:var(--surface);min-height:28px;font-size:12.5px}
.lcard .fbar-body .chips{margin:0}
.lstrip-right .fbar-tag,.dash-strip-left .fbar-tag{font-size:12px}

/* Activity: the type chips sit in a band under the strip. */
.lchips{padding:8px 20px;background:var(--surface-2);border-bottom:1px solid var(--line)}
.lchips .chips{margin:0;gap:4px}
.lchips .chips a{min-height:28px;padding:0 10px;font-size:12.5px;border-color:transparent;background:transparent;color:var(--ink-3)}
.lchips .chips a:hover{background:var(--surface);border-color:var(--line)}
.lchips .chips a[aria-current='true']{background:var(--surface);border-color:var(--line);color:var(--ink);font-weight:600}
.lchips .chips a .c{opacity:.6}

/* Accounting: the journal table lives in the same card under the same
   strip; header 12px grey, 52px rows, tabular right-aligned amounts, quiet
   28px row actions. The KPI row is one card of hairline-separated cells. */
/* position:relative is NOT decoration here — it is what makes the scroll box
   actually contain the table.
   An 'overflow' clip does not apply to an absolutely positioned descendant
   whose containing block sits OUTSIDE the scrolling element. The header cell
   for the row actions carries a visually-hidden <span class="sr">, and .sr is
   position:absolute; with this wrapper static, that span's containing block
   was .wrap, so it escaped the clip and was laid out at the far edge of the
   926px-wide table. The document grew to ~923px on a 390px phone, the browser
   zoomed the whole portal out to fit, and every control shrank with it —
   which is why taps on /portail/comptabilite missed and had to be repeated.
   Making the wrapper a containing block keeps the span inside the scroller. */
.tablewrap{overflow-x:auto;position:relative}
.lcard table{border:0;border-radius:0;margin:0}
.lcard th{padding:10px 12px;color:var(--ink-3)}
.lcard td{padding:12px;color:var(--ink-2)}
.lcard th:first-child,.lcard td:first-child{padding-left:20px}
.lcard th:last-child,.lcard td:last-child{padding-right:20px}
.lcard td strong{color:var(--ink);font-weight:600}
.lcard td.rowacts{padding-left:8px !important}
.lcard .rowact{min-width:28px;height:28px;padding:0 6px;justify-content:center;border-radius:var(--r-sm)}
.lcard .rowact svg{width:14px;height:14px}
.lcard .rowdel button{min-height:0}
.stats-card{padding:6px 20px}
.stats-card .stats{margin:0 -8px}
.subtabs a{font-size:13px}
.lstrip-count{font-size:12.5px;color:var(--ink-4);white-space:nowrap}

/* Activity: the audit log rows take the row rhythm of the list card. */
.lcard>.log{margin:0}
.lcard>.log li{padding:12px 20px;min-height:52px;align-items:center}
.lcard>.log li:first-child{padding-top:12px}
.lcard>.log li:last-child{padding-bottom:12px}

@media (max-width:1000px){
  .lhead{display:none}
  .lcard>.dash-list>.crow{flex-wrap:wrap}
  .lcard>.dash-list>.crow>.crow-body{flex:1 1 60%}
  .lcard>.dash-list>.crow>.right{flex:1 1 100%;margin-top:6px;padding-left:40px;flex-wrap:wrap;gap:8px 12px}
  .lc-status,.lc-date{width:auto}
  .lc-acts{margin-left:auto}
}
@media (max-width:640px){
  .lcard>.dash-strip,  .lcard>.dash-list>.crow{padding:12px 16px}
  .lcard .fbar-body,.lfoot,.lcard>.bulkbar{padding-inline:16px}
  .lstrip-right{margin-left:0;width:100%}
  .lsearch,.lsearch input{width:100%}
  .lcard>.dash-list>.crow>.right{padding-left:0}
  .lcard th:first-child,.lcard td:first-child{padding-left:16px}
  .lcard th:last-child,.lcard td:last-child{padding-right:16px}
}

/* detail pages: the back link is quiet; only real actions carry the accent */
.work>a.back,.work a.backlink,.detail-back{color:var(--ink-3)}

/* ---- chart cards (piece G) -------------------------------------------
   The chart card is ONE ROW: the period's headline figure on the left, the
   plot filling the rest. Above them, the 15px title and the legend. The old
   arrangement stacked title, legend and plot with no number anywhere, so the
   card showed a shape and made the reader hunt the KPI strip for the value
   that shape belongs to.

   The left block is a third of the card and never narrower than 200px — the
   figure is the widest thing in it and a "1 234 567,00 €" that wraps mid-
   number is worse than a narrower plot. */
/* The card is stretched to its taller neighbours by the grid, so the body
   claims that height rather than centring in it and leaving a band of empty
   card under the plot. */
.chart-body{display:flex;align-items:center;gap:16px;min-width:0;flex:1 1 auto}
/* Optical centring, side-by-side only: the plot reserves a band at its foot for
   the date labels, so a box-centred figure sits above the drawing's own centre
   line and reads as pinned to the top. Nudge it down onto the line. */
@media (min-width:1181px){.chart-body>.chart-lede{margin-top:26px}}
/* A dense series needs the whole card. Below this the lede sits above the plot
   instead of beside it — the figure reads the same either way, the chart does
   not. */
@media (max-width:1180px){
  .chart-body{flex-direction:column;align-items:stretch;gap:10px}
  .chart-lede{flex:0 0 auto;max-width:none;flex-direction:row;align-items:baseline;gap:12px;flex-wrap:wrap}
  .chart-lede-d{margin-left:auto}
}
/* 240px, not 200: the chip and its caption sit on ONE line in the reference,
   and at 200 "vs. période précédente" wrapped under the pill — which reads as
   a third fact rather than as the chip's own footnote. */
.chart-lede{flex:0 1 auto;min-width:140px;max-width:200px;display:flex;flex-direction:column;gap:6px}
/* The label belongs TO the figure, so it sits tight against it — the block's
   own 6px gap is the spacing between the figure and the delta chip below,
   which is a separate fact. */
/* Louder than a plain .eyebrow. At 11px/500 in the faintest ink this label
   sat so far back that the figure read as unlabelled — and this one is doing
   real work, because "-326,94 €" in red means nothing until you know whether
   it is the total, the net or the balance. A step up in size, weight and ink
   keeps it subordinate to the number while making it legible at a glance.
   Scoped to the chart lede: the shared .eyebrow captions whole sections, where
   the quiet version is right. */
.chart-lede-l{margin:0 0 2px;font-size:11.5px;font-weight:600;color:var(--ink-3);letter-spacing:.06em}
/* Near-black and 34px: the reference keeps the figure neutral and lets the
   chip carry the colour, because a green number plus a green chip says the
   same thing twice and leaves nothing to mark the exception. */
/* clamp, not a fixed size: "1 234 567,00 €" at a hard 34px overflows the
   column on a laptop, and shrinking the whole card to fit one long figure is
   the wrong trade. */
.chart-lede-n{margin:0;font-size:clamp(26px,2.4vw,34px);line-height:1.05;font-weight:600;
  color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.chart-lede-d{margin:0;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
/* A period with no comparison renders this row empty — height 0, but still a
   flex child, so the column's gap left 13px of dead space UNDER the figure.
   The block is centred against the plot, so that padding pushed the number
   visibly high in a card whose whole job is to present it. Removing the empty
   row from layout puts the figure's real mass on the centre line. */
.chart-lede-d:empty{display:none}
/* The headline figure states the verdict: green when the period is in profit,
   red when it is at a loss. Not the series cyan — that was the same colour
   whichever way the period went, so the one number the card exists to deliver
   said nothing until you read its minus sign. (It was also 2.90:1 as a 34px
   figure on white; these two clear 4.5.) A zero period stays neutral ink:
   breaking even is neither. */
.chart-lede-n.is-gain{color:var(--gain)}
.chart-lede-n.is-loss{color:var(--loss)}
/* The chip is the .stat .d pill, borrowed so the chart card and the KPI cells
   above it cannot drift into two different green. */
.chart-lede-d .d{font-size:12px;font-weight:500;padding:3px 8px;border-radius:99px;
  white-space:nowrap;line-height:1.5;display:inline-block}
.chart-lede-d .d.up{background:var(--ok-soft);color:var(--ok-ink)}
.chart-lede-d .d.down{background:var(--bad-soft);color:var(--bad-ink)}
.chart-lede-d .d.flat{background:var(--surface-3);color:var(--ink-4)}
.chart-plot{flex:1 1 auto;min-width:0;align-self:stretch;display:flex;align-items:center}
/* The plot column is narrower than the card, so the viewBox ratio makes the
   SVG short while the grid stretches the card to its taller siblings — the
   drawing ended up floating in a band of empty white. Letting the svg fill the
   column and giving it "none" removes both problems: the chart uses the height
   the card actually has, and because the axis labels are drawn ON the svg they
   scale with it rather than detaching from their gridlines. */
.chart-plot .mc{width:100%}
.chart-plot .mc svg{min-height:150px}
/* Not height:100% on the svg: preserveAspectRatio is "meet", so a box taller
   than the ratio needs letterboxes the drawing inside it — which is the blank
   band we are trying to remove, just moved inside the SVG. The fix is to stop
   the CARD stretching to its taller siblings, so the row sizes to the chart. */
/* The three cards share a row, so they share a height: a row of panels at
   three different heights reads as a layout accident. The chart card no longer
   needs align-items:start to avoid a stretched drawing — .chart-body centres
   itself in whatever height the row gives it. */
.chartrow{align-items:stretch}
.chartrow>.card{min-height:0}
.chart-side{display:flex;flex-direction:column}
/* The category list sits at the TOP of its card with its footer pinned,
   rather than floating in the middle of a tall panel. */
.chart-side>.ranklist{margin-bottom:auto}
/* Only a genuinely narrow card stacks. The breakpoint is the phone one, not
   the desktop one: at 1080px the chart card goes full width and has MORE room
   for the row, not less, so stacking there would have been backwards. */
@media (max-width:720px){
  .chart-body{flex-direction:column;align-items:stretch;gap:10px}
  .chart-lede{flex:0 0 auto;min-width:0;gap:4px}
  .chart-lede-n{font-size:28px}
}

/* The four accounting KPI cells are four different KINDS of figure — money
   in, money out, what is left, what is owed the state — so each takes one
   hue as a left border and a matching bar at its foot. That is the reference's
   category treatment and it is deliberately NOT applied to the dashboard's
   metric grids, where every cell is the same kind of thing counted for a
   different object and four hues would only invent a taxonomy. */
.kpi-cats .stats.is-inset>.stat.kpi-cat{position:relative;
  border-left:0;padding-left:15px;padding-bottom:16px}
.kpi-cats .stats.is-inset>.stat.kpi-cat::before{content:'';position:absolute;
  left:0;top:2px;bottom:0;width:14px;pointer-events:none;
  border-left:3px solid var(--kpi-hue);border-bottom:3px solid var(--kpi-hue);
  border-bottom-left-radius:8px}
/* The foot bar starts at the LEFT EDGE, flush with the border above it, so the
   two read as one continuous L around the cell — inset by 12px they floated
   apart and the cell looked like it had two unrelated marks. Square on that
   corner for the same reason: a pill end cannot meet a straight border. */
.kpi-cats .stats.is-inset>.stat.kpi-cat::after{content:'';position:absolute;
  left:14px;right:14px;bottom:0;height:3px;border-radius:0 99px 99px 0;
  background:var(--kpi-hue)}
.kpi-cats .stats.is-inset>.stat.kpi-cat .stat-icon{color:var(--kpi-hue)}
/* The four KPI hues say what each figure IS, and match the chart's legend:
     Recettes    blue    — the accent, one blue in the interface
     Dépenses    orange  — same orange as the expense series and the bars below
     Résultat    green or red, set by .is-gain / .is-loss on the tile
     Solde TVA   amber   — neither good nor bad, a balance to settle
   Dépenses was grey, which made the second-largest figure on the page the
   only colourless one. */
.stat.kpi-1{--kpi-hue:var(--fin-income)}
.stat.kpi-2{--kpi-hue:var(--fin-expense)}
.stat.kpi-3{--kpi-hue:var(--ink-3)}
.stat.kpi-3.is-gain{--kpi-hue:var(--gain)}
.stat.kpi-3.is-loss{--kpi-hue:var(--loss)}
.stat.kpi-4{--kpi-hue:var(--fin-vat)}
/* The result's own FIGURE carries the verdict too, not just its rule: a red
   bar under a black number still reads as neutral at a glance. */
.stat.kpi-3.is-gain .n{color:var(--gain)}
.stat.kpi-3.is-loss .n{color:var(--loss)}
@media (max-width:640px){
  .kpi-cats .stats.is-inset>.stat.kpi-cat::after{right:8px;left:14px}
}

/* ── Phone density ──────────────────────────────────────────────────────
   The desktop layout is right and is left alone. On a phone the four KPI
   tiles fell to ONE column — four full-width cards ~106px tall, so the
   figures alone filled most of a screen and the journal (the thing you came
   for) started below the fold. The VAT gauge did the same: a full-size ring
   for one number.

   Two columns rather than one. These are four short label/figure pairs, not
   content that needs width: at 2×2 the whole set is read in one glance and
   costs half the height. The 176px floor is what forced a single column at
   375px, so it drops here. */
@media (max-width:560px){
  .kpi-cats .stats.is-inset{grid-template-columns:1fr 1fr}
  .kpi-cats .stats.is-inset>.stat.kpi-cat{padding:10px 10px 12px}
  /* Every tile keeps its left rule, not just the ones that happened to fall
     in the first column. */
  .stats.is-inset>.stat:not(:first-child){padding-left:10px}
  .kpi-cats .stats.is-inset>.stat .l{margin-bottom:5px;font-size:12px}
  .kpi-cats .stats.is-inset>.stat .n{font-size:19px;line-height:1.1}
  /* The foot ("hors TVA", the delta chip) is the least load-bearing line on
     a tile and the first thing worth spending. */
  .kpi-cats .stats.is-inset>.stat .f{font-size:11px;margin-top:2px}
  .kpi-cats .stats.is-inset>.stat.kpi-cat::after{left:10px;right:10px}

  .chartrow>.card{gap:9px}

  /* The plot keeps its shape but loses the dead height a phone cannot use. */
  .chart-main .chart-plot svg{height:auto}
  .chart-lede-n{font-size:24px}
}
/* ---- end chart cards (piece G) ---------------------------------------- */

/* ---- mail (Courrier) --------------------------------------------------- */
/* Three surfaces inside the workbench: a narrow folder rail, then either the
   list or the reading pane / composer. Same tokens as everything else — the
   mailbox is one more instrument on the bench, not a different app. */
.mail{display:grid;grid-template-columns:208px minmax(0,1fr);gap:16px;align-items:start}
.mail-side{position:sticky;top:16px;display:flex;flex-direction:column;gap:12px}
.mfolds{display:flex;flex-direction:column;gap:2px}
/* Whose mail is on screen. Same shape as a folder row so the rail reads as one
   list, separated by a rule because it answers a different question. */
.mbox-pick{display:flex;flex-direction:column;gap:2px;margin:0 0 10px;padding:0 0 10px;
  border-bottom:1px solid var(--line)}
.mbox-pick button{display:flex;align-items:center;gap:9px;min-height:32px;padding:0 10px;
  border-radius:var(--r);border:0;background:none;width:100%;text-align:left;cursor:pointer;
  font-family:inherit;font-size:13px;font-weight:500;color:var(--ink-2)}
.mbox-pick button svg{color:var(--ink-4);flex:0 0 auto}
.mbox-pick button span{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mbox-pick button:hover{background:var(--surface-2);color:var(--ink)}
.mbox-pick button.is-active{background:var(--accent-soft);color:var(--accent-ink)}
.mfold{display:flex;align-items:center;gap:9px;min-height:36px;padding:0 10px;border-radius:var(--r);
  color:var(--ink-2);font-size:13.5px;font-weight:500;text-decoration:none;border:0;background:none;
  width:100%;text-align:left;cursor:pointer;font-family:inherit}
.mfold svg{color:var(--ink-4);flex:0 0 auto}
.mfold span:first-of-type{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mfold:hover{background:var(--surface-2);color:var(--ink);text-decoration:none}
.mfold.is-active{background:var(--accent-soft);color:var(--accent-ink)}
.mfold.is-active svg{color:var(--accent)}
.mfold-n{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:11.5px;color:var(--ink-4);
  font-variant-numeric:tabular-nums}
.mfold-n.is-unread{color:var(--accent-ink);font-weight:600}
.mfold.as-btn{min-height:36px}
.mside-foot form{margin:0}
.dash-fleet{display:flex;align-items:center;gap:8px;margin:-8px 0 16px 4px;font-size:13px;color:var(--ink-3)}
.dash-fleet svg{color:var(--ok)}
.dash-fleet.is-bad svg{color:var(--bad)}
.dash-fleet a{color:inherit}
.mquota{padding:10px 10px 4px;border-top:1px solid var(--line)}
.mquota .hint{margin:6px 0 0}
.mquota-bar{height:5px;border-radius:99px;background:var(--surface-3);overflow:hidden}
.mquota-bar>span{display:block;height:100%;background:var(--accent);border-radius:99px;min-width:2px}
.mail-main{min-width:0}
.mail-list,.mail-read{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:0;overflow:hidden}
.mlist-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  padding:12px 16px;border-bottom:1px solid var(--line)}
.mlist-head h2{margin:0;font-size:15px}
.msearch{margin:0}
.mlist-head .lsearch input{width:260px;max-width:100%}
/* A flash inside the list card runs edge to edge, as one more row. */
.mail-list .ok,.mail-list .err{margin:0;border-radius:0;border-bottom:1px solid var(--line)}
/* Bulk bar: select-all, a hairline, then quiet text buttons. It sits on the
   same white as the rows and only reads as a toolbar once something is
   ticked — the rows are the content, the bar is not. */
.mbulk-bar{display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:6px 10px 6px 8px;
  border-bottom:1px solid var(--line-soft);min-height:42px}
.mbulk-bar .spacer{flex:1 1 auto}
.mbulk-sep{width:1px;height:18px;background:var(--line);margin:0 6px 0 2px;flex:0 0 auto}
.mbulk-acts{display:inline-flex;align-items:center;gap:2px;flex-wrap:wrap}
.mbulk{min-height:30px;padding:0 9px;font-size:12.5px;gap:6px;display:inline-flex;align-items:center;
  background:none;border:1px solid transparent;box-shadow:none;color:var(--ink-3);font-weight:500}
.mbulk svg{color:var(--ink-4)}
.mbulk:hover{background:var(--surface-2);border-color:transparent;color:var(--ink)}
.mbulk:hover svg{color:var(--ink-2)}
.mbulk.is-danger{color:var(--bad-ink)}
.mbulk.is-danger svg{color:var(--bad)}
.mbulk.is-danger:hover{background:var(--bad-soft);border-color:transparent;color:var(--bad-ink)}
.mrow-check{display:inline-flex;align-items:center;justify-content:center;width:28px;min-height:28px;flex:0 0 auto}
.mrow-check input{width:15px;height:15px;min-height:0;margin:0;accent-color:var(--accent)}
.mlist{list-style:none;margin:0;padding:0}
.mrow{display:flex;align-items:center;gap:4px;padding:0 10px 0 8px;border-bottom:1px solid var(--line-soft);
  min-height:44px;position:relative}
.mrow:last-child{border-bottom:0}
.mrow:hover{background:var(--surface-2)}
.mrow.is-open{box-shadow:inset 3px 0 0 var(--accent)}
.mrow-star{appearance:none;background:none;border:0;padding:0;width:28px;min-height:28px;display:inline-flex;
  align-items:center;justify-content:center;color:var(--ink-5);cursor:pointer;border-radius:var(--r-sm);flex:0 0 auto;position:relative;z-index:2}
.mrow-star:hover{color:var(--warn);background:var(--surface-3)}
.mrow-star.is-on{color:var(--warn)}
.mrow-main{display:grid;grid-template-columns:minmax(150px,210px) minmax(0,1fr) auto;gap:12px;align-items:center;flex:1 1 auto;
  min-width:0;padding:10px 4px;color:inherit;text-decoration:none}
.mrow-main:hover{text-decoration:none;color:inherit}
.mrow-who{font-size:13.5px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:flex;gap:6px;align-items:center}
.mrow-subj{font-size:13.5px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.mrow-s{color:var(--ink-2)}
.mrow-end{display:inline-flex;align-items:center;gap:8px;color:var(--ink-4);font-size:12px;white-space:nowrap;
  font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums}
.mrow-end svg{color:var(--ink-4)}
.mrow.is-unread .mrow-who,.mrow.is-unread .mrow-s{font-weight:600;color:var(--ink)}
.mrow.is-unread .mrow-end time{color:var(--accent-ink);font-weight:600}
.mail-list .empty{padding:36px 16px;text-align:center}
.mail-list .pager{margin:0;padding:12px}
.mail-read{padding:14px 18px 18px}
.mread-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-bottom:12px}
.mread-back{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--ink-3);text-decoration:none}
.mread-back svg{transform:rotate(180deg)}
.mread-back:hover{color:var(--ink)}
.mtools{display:flex;gap:6px;flex-wrap:wrap}
.mtools form{margin:0}
.mact{min-height:32px;padding:0 10px;font-size:12.5px;gap:5px;display:inline-flex;align-items:center}
.mact.is-danger{color:var(--bad-ink)}
.mact.is-danger:hover{background:var(--bad-soft);border-color:var(--bad-line)}
.mread-subj{font-size:18px;margin:0 0 10px;line-height:1.3;overflow-wrap:anywhere}
.mread-meta{display:flex;flex-direction:column;gap:3px;font-size:13px;color:var(--ink-3);padding-bottom:12px;
  border-bottom:1px solid var(--line);margin-bottom:12px;overflow-wrap:anywhere}
.mread-k{display:inline-block;min-width:44px;color:var(--ink-4)}
.mspam{margin:0 0 10px;padding:8px 12px;border-radius:var(--r);background:var(--bad-soft);color:var(--bad-ink);font-size:12.5px}
.mimages{margin:0 0 10px;padding:8px 12px;border-radius:var(--r);background:var(--warn-soft);color:var(--warn-ink);font-size:12.5px}
.mimages a{color:inherit;font-weight:600;text-decoration:underline}
.matts{list-style:none;margin:0 0 12px;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.matts a{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--line);border-radius:var(--r);
  font-size:12.5px;color:var(--ink-2);text-decoration:none;background:var(--surface-2)}
.matts a:hover{border-color:var(--line-strong);background:var(--surface-3)}
.mbody{display:block;width:100%;min-height:360px;border:1px solid var(--line);border-radius:var(--r);background:#fff}
.mcomp .frow{margin-bottom:10px}
.mcc{margin:0 0 10px}
.mcc>summary{cursor:pointer;font-size:12.5px;color:var(--ink-3);list-style:none}
.mcc>summary::-webkit-details-marker{display:none}
.mcc>summary::before{content:"+ "}
.mcc[open]>summary::before{content:"\2013  "}
.mcc .frow{margin-top:8px}
.mcomp .cardfoot .is-danger{color:var(--bad-ink)}
.mlock{max-width:560px;padding:28px 28px 24px}
.mlock-icon{width:44px;height:44px;border-radius:var(--r);display:grid;place-items:center;background:var(--accent-soft);
  color:var(--accent);margin-bottom:12px}
.mlock h2{margin:0 0 6px}
.mlock form{margin-top:14px}
.mrank{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px;font-size:13px}
.mrank>li{display:flex;justify-content:space-between;gap:10px;overflow-wrap:anywhere}
.mrank strong{font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums}
@media (max-width:1000px){
  .mail{grid-template-columns:1fr}
  .mail-side{position:static;flex-direction:row;flex-wrap:wrap;align-items:center}
  .mfolds{flex-direction:row;flex-wrap:wrap;gap:4px}
  .mfold{min-height:32px;padding:0 9px;font-size:13px;width:auto}
  .mquota{border-top:0;padding:0;flex:1 1 100%}
  .mside-foot{display:flex;gap:6px}
  .mrow-main{grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto}
  .mrow-who{grid-column:1}
  .mrow-end{grid-column:2;grid-row:1/3}
  .mrow-subj{grid-column:1}
}
/* The header's settings cog exists for phones; desktop keeps the rail link. */
.mail-cog{display:none}
@media (max-width:640px){
  /* Phone mail: the folders are one scrolling row and nothing else sits
     above the inbox. Quota and send count live in the mailbox settings,
     which moved beside "Nouveau message" in the header. */
  .mail{gap:10px;grid-template-columns:minmax(0,1fr)}
  .mail-side{gap:0;min-width:0}
  .mbox-pick{flex-direction:row;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;width:100%;margin:0 0 6px;padding:0 0 6px}
  .mbox-pick::-webkit-scrollbar{display:none}
  .mbox-pick button{flex:0 0 auto}
  .mfolds{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;width:100%;min-width:0;gap:2px;padding-bottom:2px}
  .mfolds::-webkit-scrollbar{display:none}
  .mfold{flex:0 0 auto;min-height:34px;padding:0 10px}
  .mquota,.mside-foot{display:none}
  .mail-cog{display:inline-flex;padding:9px 10px}
  .mail-cog.is-on{background:var(--accent-soft);color:var(--accent-ink)}
  .mlist-head{padding:10px 12px}
  .mlist-head .lsearch{flex:1 1 100%}
  .mlist-head .lsearch input{width:100%}
  /* The bulk bar is a toolbar for a selection. With nothing ticked it is six
     buttons between the reader and the first message; hide it until then. */
  .mbulk-bar{display:none}
  .mail-list:has(.mrow-check input:checked) .mbulk-bar{display:flex}
  .mall{display:none}
}
/* Mailbox admin — list rows and the management dialog. */
.dash-list>.crow>.itile{flex:0 0 auto}
.num{font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;font-size:.95em}
.crow .meta .num{color:var(--ink-3)}
.mlead{margin:0 0 16px}
.mlead .lead-copy h2{font-size:16px}
.dlg-body .factlist{margin:0}
.factlist dd .num{font-size:13px;color:var(--ink)}
.mtops{margin-top:18px;padding-top:16px;border-top:1px solid var(--line-soft)}
.mtop h4{margin:0 0 8px;font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4)}
.mrank>li{padding:5px 0;border-bottom:1px solid var(--line-soft);color:var(--ink-2)}
.mrank>li:last-child{border-bottom:0}
.mrank-empty{margin:0;font-size:13px;color:var(--ink-4)}
.acc-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:14px}
.msuspend{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}
.msuspend>div{flex:1 1 240px;min-width:0}
.msuspend>div>label{margin-top:0}
.msuspend>button.danger{background:none;border:1px solid var(--bad-line);color:var(--bad-ink);font-weight:500;box-shadow:none;min-height:40px}
.msuspend>button.danger:hover{background:var(--bad-soft)}
.confirm-actions{margin-top:12px}
.confirm-body label{margin-top:0}
/* Account dialog — lead card, option rows, login rows, disclosure folds. */
.acc-sec>h3+form>.row>div>label{margin-top:0}
.optlist{margin:16px 0 0;border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden}
.optrow{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;margin:0;cursor:pointer;color:var(--ink)}
.optrow+.optrow{border-top:1px solid var(--line-soft)}
.optrow:hover{background:var(--surface-2)}
.optrow input[type='checkbox']{width:16px;height:16px;flex:0 0 auto;margin:2px 0 0;min-height:0;accent-color:var(--accent)}
.optrow-copy{display:flex;flex-direction:column;gap:2px;min-width:0}
.optrow-t{font-size:13.5px;font-weight:500;color:var(--ink)}
.optrow-h{font-size:12.5px;line-height:1.5;color:var(--ink-4)}
.optrow input[type='radio']{width:16px;height:16px;flex:0 0 auto;margin:2px 0 0;min-height:0;accent-color:var(--accent)}
/* Password mode: one choice list; the password field only appears once "set it now" is picked. */
.modes{border:0;padding:0;margin:14px 0 0;min-width:0}
.modes-list{margin:0}
.modes-pw{margin-top:14px}
.modes-pw>label{margin-top:0}
/* The submit label follows the chosen mode: one span per mode, only the
   selected one shown. No script — the radio is the state. The invite label is
   the DEFAULT rather than another :has() rule, so a browser without :has()
   still shows a labelled button instead of an empty one. */
/* The role picker belongs to a STAFF address: the domain decides the role, so
   the picker follows the domain rather than standing there asking a question
   that does not apply to a client. */
.rolepick-wrap{display:none}
form:has(select[name='domain'] option[data-admin]:checked) .rolepick-wrap{display:block}
.lbl{display:none}
.lbl-invite{display:inline}
form:has(input[name='mode'][value='set']:checked) .lbl-invite,
form:has(input[name='mode'][value='later']:checked) .lbl-invite{display:none}
form:has(input[name='mode'][value='set']:checked) .lbl-set,
form:has(input[name='mode'][value='later']:checked) .lbl-later{display:inline}
.modes:has(input[value='invite']:checked) .modes-pw,
.modes:has(input[value='later']:checked) .modes-pw{display:none}
.form-actions{display:flex;justify-content:flex-end;margin-top:18px}
.acc-more{margin-top:14px}
.acc-more>summary{font-size:13px}
.acc-more-body{padding:4px 0 0}
.acc-more-body>label:first-child{margin-top:0}
.acc-logins li{gap:12px;min-height:48px;padding:8px 0}
.acc-logins .itile{width:30px;height:30px}
.acc-logins .login-copy{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:1px}
.acc-logins .login-copy .mono{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acc-logins .login-copy .muted{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.acc-logins button.danger{background:none;border:1px solid transparent;color:var(--bad-ink);box-shadow:none;font-weight:500}
.acc-logins button.danger:hover{background:var(--bad-soft);border-color:transparent}
.acc-logins button.ghost{min-height:28px}
.acc-fold{margin-top:10px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.acc-fold>summary{display:flex;align-items:center;gap:10px;padding:0 14px;min-height:44px;font-size:13.5px;
  font-weight:500;color:var(--ink-2);cursor:pointer;border-radius:var(--r-md)}
.acc-fold>summary:hover{background:var(--surface-2);color:var(--ink)}
.acc-fold>summary>svg{width:15px;height:15px;color:var(--ink-4);flex:0 0 auto}
.acc-fold>summary::before{content:none}
.acc-fold>summary::after{content:'›';margin-left:auto;font-size:18px;line-height:1;color:var(--ink-4);
  transition:transform .15s var(--ease)}
.acc-fold[open]>summary{margin-bottom:0;color:var(--ink);border-bottom:1px solid var(--line-soft);
  border-radius:var(--r-md) var(--r-md) 0 0}
.acc-fold[open]>summary::after{transform:rotate(90deg)}
.acc-fold-body{padding:14px}
.acc-fold-body>form>.row>div>label{margin-top:0}
.acc-inline{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.acc-inline>.hint{flex:1 1 260px}
.acc-inline>button{flex:0 0 auto}
.acc-sub{margin-top:16px;padding-top:16px;border-top:1px solid var(--line-soft)}
.acc-sub .row>div>label{margin-top:0}
.confirm-body .hint{margin:0 0 10px}
/* ---- end mail ----------------------------------------------------------- */

/* Dashboard usability improvements; original navigation and palette retained. */
.workspace-picker{position:relative}
.workspace-picker>summary{cursor:pointer;list-style:none}
.workspace-picker>summary::before,.workspace-picker>summary::after{content:none}
.workspace-picker>summary::-webkit-details-marker{display:none}
.workspace-picker>summary>svg{margin-left:auto;flex-shrink:0}
.workspace-options{display:flex;flex-direction:column;max-height:240px;overflow:auto;padding:4px;background:var(--surface);border-radius:8px}
.workspace-options a{padding:10px;color:var(--ink);border-radius:4px}
.workspace-options a:hover,.workspace-options a[aria-current]{background:var(--surface-3)}

/* ── identity menu ────────────────────────────────────────────────────────
   The rail's identity control opens ONE menu holding both the workspace list
   and everything personal to the login. It floats over the page rather than
   pushing the navigation down, and it is grouped by hairlines with a quiet
   caption per group — the row is the whole hit area, 13px, no icons. */
.acct-menu{position:absolute;top:calc(100% + 6px);left:0;z-index:60;
  width:max(100%,248px);max-height:min(70vh,420px);gap:1px;padding:5px;
  border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-lg)}
.acct-menu .acct-label{margin:0;padding:7px 10px 4px;font-size:11px;font-weight:600;
  letter-spacing:.04em;text-transform:uppercase;color:var(--ink-4)}
.acct-menu hr{height:1px;flex:0 0 auto;margin:5px 0;border:0;background:var(--line)}
.acct-menu a,.acct-menu button{display:flex;align-items:center;width:100%;
  padding:8px 10px;border-radius:var(--r-sm);font:inherit;font-size:13px;
  color:var(--ink-2);text-align:left;text-decoration:none}
.acct-menu button{appearance:none;background:none;border:0;cursor:pointer;min-height:0}
.acct-menu a:hover,.acct-menu button:hover{background:var(--surface-3);color:var(--ink)}
.acct-menu a:focus-visible,.acct-menu button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* The workspace you are already in keeps a check, not a highlight: a filled
   row next to the hovered row read as two selections at once. */
.acct-menu a[aria-current]{color:var(--ink);font-weight:500}
.acct-menu a[aria-current]::after{content:'✓';margin-left:auto;color:var(--accent);font-size:12px}
.acct-menu form{margin:0}
/* The count is part of the title, not glued to it: an inline-flex h2 keeps the
   gap even when the markup's whitespace is collapsed. */
.card-hd h2{display:inline-flex;align-items:baseline;gap:6px}
.project-count{margin-left:0;font-weight:500}

/* The header is a band, the list is the body: one hairline between them, run
   edge to edge like every other list in the portal. Without it the first row
   floats under the title and the card reads as one undivided block. */
.dash-card .card-hd:has(+.dash-list){margin-bottom:0;padding-bottom:14px}
.dash-card .card-hd+.dash-list{border-top:1px solid var(--line)}
.dash-list>.crow+.crow{border-top:1px solid var(--line-soft)}

.dash-list>.project-summary{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.dash-list>.project-summary>.crow-body{flex:1 1 240px;min-width:0}
.project-summary .msg{display:block;white-space:normal;overflow-wrap:anywhere;-webkit-line-clamp:unset;line-clamp:unset}
/* Fixed slots on the right so the badge, the percentage and the arrow line up
   as columns down the list instead of drifting with each row's label width.
   The percentage is measured, so it is mono and tabular. */
.project-summary>.right{flex:0 0 auto;display:flex;align-items:center;gap:10px}
.project-summary>.right>.badge{min-width:92px;justify-content:center}
.project-summary>.right>.pill{min-width:52px;justify-content:center;
  font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums}
.dashboard-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:24px;align-items:start}
.dashboard-columns>div{min-width:0}
.dashboard-columns .stats{grid-template-columns:repeat(2,minmax(0,1fr))}
.task-card .metrics{margin:0 0 12px;justify-content:flex-start}
.task-card .metric{min-height:44px}
.task-card .clist{margin-bottom:0}
.dash-clear{padding:16px 0 0}
.dash-clear .sub{margin:4px 0 0}
.health-summary .sub{margin:0}
.health-summary .dash-fleet{margin:0}
.dashboard-fold{margin:0 0 24px}
.dashboard-fold>summary,.analytics-fold>summary,.progress-override>summary,.historical-check>summary{min-height:44px;display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--link)}
.dashboard-fold[open]>.dash-card{margin-top:12px}
.analytics-fold{margin-top:16px;border-top:1px solid var(--line)}
.analytics-fold .chartrow{margin-top:12px}
.progress-override{margin-top:20px;border-top:1px solid var(--line)}
.progress-override input{max-width:160px}
.historical-check{margin:12px 0}
.dashboard-columns .log{margin-bottom:0}
.dashboard-columns .log li{overflow-wrap:anywhere}
.task-card .nm{font-weight:600}
.task-card .crow{gap:12px}
.dashboard-columns .dash-card .card-hd{flex-wrap:wrap}
.segbar{flex-wrap:wrap}
@media (max-width:1100px){.dashboard-columns{grid-template-columns:minmax(0,1fr)}}

.side-top>.workspace-picker{flex:1;min-width:0}
@media (max-width:860px){.dashboard-columns{gap:0}.topbar{height:auto;min-height:0}}

/* Audience explorer: one chart and one switchable ranking, no nested cards. */
.audience-explorer.chartrow{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(280px,1fr);gap:32px;padding-top:24px;border-top:1px solid var(--line);margin-top:20px;align-items:start}
.audience-heading{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap}
.audience-heading h2{margin:0}
.audience-readout{display:flex;align-items:baseline;gap:10px;min-height:54px;margin:20px 0 12px;color:var(--ink-3);font-size:12px}
.audience-readout strong{font-size:30px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.audience-chart{height:220px;display:flex;gap:12px}
.audience-scale{display:flex;flex-direction:column;justify-content:space-between;font-size:11px;color:var(--ink-4);min-width:24px}
.audience-bars{flex:1;display:flex;gap:4px;min-width:0;background:linear-gradient(to bottom,var(--line) 1px,transparent 1px);background-size:100% 50%;border-bottom:1px solid var(--line)}
button.audience-day{position:relative;display:flex;align-items:flex-end;justify-content:stretch;flex:1;min-width:0;height:100%;min-height:0;padding:0;border:0;border-radius:4px;background:transparent;box-shadow:none;cursor:crosshair}
button.audience-day>span{display:block;width:100%;height:max(2px,var(--day-height));background:var(--accent);opacity:.24;border-radius:4px 4px 0 0;transition:opacity .15s}
button.audience-day:hover>span,button.audience-day:focus-visible>span,button.audience-day.is-selected>span{opacity:1}
button.audience-day:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.audience-dates{display:flex;justify-content:space-between;margin:12px 0 0 36px;font-size:11px;color:var(--ink-4)}
.audience-breakdown{min-width:0;border-left:1px solid var(--line);padding-left:28px}
.audience-tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);padding-bottom:10px;flex-wrap:wrap}
.audience-tabs button{background:transparent;box-shadow:none;border:0;border-radius:6px;color:var(--ink-3);font-size:12px;min-height:40px;padding:8px 10px}
.audience-tabs button[aria-selected='true']{background:var(--accent-soft);color:var(--accent-ink)}
.audience-panel{padding-top:18px;min-height:260px}
.audience-panel[hidden]{display:none}
.audience-panel .hint{margin-top:20px}
.audience-panel .rank-track{max-width:none;height:5px}
.audience-panel .ranklist{gap:18px}
.audience-panel .rank-label{white-space:normal;overflow-wrap:anywhere}
@media(prefers-reduced-motion:reduce){button.audience-day>span{transition:none}}
@media(max-width:1000px){.audience-explorer.chartrow{grid-template-columns:minmax(0,1fr)}.audience-breakdown{padding:20px 0 0;border-left:0;border-top:1px solid var(--line)}.audience-panel{min-height:0}}
@media(max-width:480px){.audience-chart{height:180px}.audience-bars{gap:2px}.audience-tabs button{padding:8px;font-size:11px}}

/* ── dashboard colour layer ──────────────────────────────────────────────
   The dashboard read as one grey sheet: every pill, tile icon, arrow and
   badge sat on --surface-3 in --ink-4. Each element now carries the hue of
   the thing it stands for — blue for inbox/work, green for money in and
   sites up, amber for waiting, pink for overdue/loss, purple for projects.
   Contrast still comes from the -ink tokens; the hue lives in the icon
   tile, the pill fill and a small dot beside the card title. */
.dash-card{--dash-hue:var(--accent);--dash-hue-soft:var(--accent-soft)}
.dash-card>.card-hd h2{display:inline-flex;align-items:center;gap:8px}
.dash-card>.card-hd h2::before{content:'';width:8px;height:8px;border-radius:99px;flex:0 0 auto;
  background:var(--dash-hue);box-shadow:0 0 0 3px var(--dash-hue-soft)}
.dash-card>.card-hd>a{color:var(--accent-ink);background:var(--accent-soft);padding:0 10px;min-height:28px;border-radius:99px}
.dash-card>.card-hd>a:hover{background:var(--accent-line);color:var(--accent-ink)}
.dash-card>.card-hd>a svg{color:currentColor}
.dash-card.task-card{--dash-hue:var(--accent);--dash-hue-soft:var(--accent-soft)}
.dash-card.is-projects{--dash-hue:var(--purple);--dash-hue-soft:var(--purple-soft)}
.dash-card.is-activity{--dash-hue:var(--info);--dash-hue-soft:var(--info-soft)}
.dash-card.is-books{--dash-hue:var(--ok);--dash-hue-soft:var(--ok-soft)}
.dash-card.health-summary,.dash-card.is-sites{--dash-hue:var(--ok);--dash-hue-soft:var(--ok-soft)}
.dash-card.is-perf{--dash-hue:var(--warn);--dash-hue-soft:var(--warn-soft)}

/* Metric pills: tinted fill, coloured glyph, coloured count. */
.dash-card .metric{background:var(--surface-2);border-color:var(--line)}
.dash-card .metric svg{color:var(--ink-3)}
.dash-card .metric.accent{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-ink)}
.dash-card .metric.accent .n,.dash-card .metric.accent svg{color:var(--accent-ink)}
.dash-card .metric.warn{background:var(--bad-soft);border-color:var(--bad-line);color:var(--bad-ink)}
.dash-card .metric.warn .n,.dash-card .metric.warn svg{color:var(--bad-ink)}
.dash-card .metric.good{background:var(--ok-soft);border-color:var(--ok-line);color:var(--ok-ink)}
.dash-card .metric.good .n,.dash-card .metric.good svg{color:var(--ok-ink)}
.dash-card .metric.is-purple{background:var(--purple-soft);border-color:transparent;color:var(--purple)}
.dash-card .metric.is-purple .n,.dash-card .metric.is-purple svg{color:var(--purple)}
.dash-card .metric.is-amber{background:var(--warn-soft);border-color:transparent;color:var(--warn-ink)}
.dash-card .metric.is-amber .n,.dash-card .metric.is-amber svg{color:var(--warn-ink)}
.dash-card a.metric:hover{filter:brightness(.96)}

/* Row tiles and arrows. */
.dash-list>.crow .itile{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.dash-list>.crow.is-overdue .itile{background:var(--bad-soft);color:var(--bad)}
.dash-list>.crow .row-go,.dash-list .row-go{background:var(--accent-soft);color:var(--accent);width:28px;height:28px;border-radius:99px}
.dash-list>.crow:hover .row-go,.dash-list .crow:hover .row-go{background:var(--accent);color:#fff}
.dash-list>.crow:hover{background:var(--accent-soft)}

/* Project badges and progress. */
.dash-card .badge.wip{background:var(--purple-soft);color:var(--purple)}
.dash-card .project-summary .pill{background:var(--accent-soft);color:var(--accent-ink)}
.dash-card .project-summary .bar>span{background:linear-gradient(90deg,var(--purple),var(--accent))}

/* KPI cells: the glyph sits in a tinted 24px chip; good/warn cells are washed. */
.dash-card .stats.is-inset>.stat .stat-icon{width:24px;height:24px;border-radius:6px;background:var(--accent-soft);color:var(--accent)}
.dash-card .stats.is-inset>.stat .stat-icon svg{width:14px;height:14px}
.dash-card .stats.is-inset>.stat.good .stat-icon{background:var(--ok-soft);color:var(--ok-ink)}
.dash-card .stats.is-inset>.stat.warn .stat-icon{background:var(--bad-soft);color:var(--bad-ink)}
.dash-card .stats.is-inset>.stat.accent .stat-icon{background:var(--accent-soft);color:var(--accent-ink)}
.dash-card .stats.is-inset>.stat.good{background:color-mix(in srgb,var(--ok-soft) 60%,var(--surface))}
.dash-card .stats.is-inset>.stat.warn{background:color-mix(in srgb,var(--bad-soft) 60%,var(--surface))}
.dash-card .stats.is-inset>.stat.good .n{color:var(--ok-ink)}
.dash-card .stats.is-inset>.stat.warn .n{color:var(--bad-ink)}
.dash-card .stats.is-inset>.stat:hover{background:var(--accent-soft)}
/* Performance strip: blue-tinted band with a solid contacts tile. */
.dash-strip{background:linear-gradient(90deg,var(--accent-soft),var(--surface-2))}
.dash-strip .itile{background:var(--accent);border-color:transparent;color:#fff}
.dash-strip .metric{background:var(--surface);border-color:var(--accent-line)}

/* Fleet line and activity avatars. */
.dash-fleet{display:flex;align-items:center;gap:8px;margin:0;padding:8px 12px;border-radius:var(--r);
  background:var(--ok-soft);color:var(--ok-ink);font-weight:500}
.dash-fleet svg{color:var(--ok);flex:0 0 auto}
.dash-fleet a{color:inherit}
.dash-fleet.is-bad{background:var(--bad-soft);color:var(--bad-ink)}
.dash-fleet.is-bad svg{color:var(--bad)}
.dash-card .log-av{background:var(--accent-soft);color:var(--accent-ink);font-weight:600}

/* ── list pages: the same hue, a lighter hand ──────────────────────────
   Row tiles and initials pick up a tint; the accounting KPI glyphs get the
   same chip as the dashboard's. Nothing else on the list pages changes. */
.lcard .crow>.itile{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.lcard .crow>.av-sm{background:var(--accent-soft);color:var(--accent-ink);font-weight:600}
.lcard .crow:nth-child(3n+2)>.av-sm{background:var(--purple-soft);color:var(--purple)}
.lcard .crow:nth-child(3n)>.av-sm{background:var(--ok-soft);color:var(--ok-ink)}
.lcard .crow.is-overdue>.itile,.lcard .crow.is-overdue>.av-sm{background:var(--bad-soft);color:var(--bad-ink)}
.lcard .crow:hover .row-go{background:var(--accent-soft);color:var(--accent)}
.stats:not(.is-inset)>.stat .stat-icon{background:var(--accent-soft);border-color:transparent;color:var(--accent)}
.stats:not(.is-inset)>.stat.good .stat-icon{background:var(--ok-soft);color:var(--ok-ink)}
.stats:not(.is-inset)>.stat.warn .stat-icon{background:var(--bad-soft);color:var(--bad-ink)}

/* ── activity feed: one hue per subject ───────────────────────────────
   The initials disc and the subject word take the colour of the thing the
   entry is about — contacts blue, projects purple, accounting green, mail
   indigo, accounts teal, logins amber, settings grey. A deletion or removal
   goes pink whatever it touched, so the eye finds it first. */
.log>li .log-av{background:var(--accent-soft);color:var(--accent-ink);font-weight:600}
.log>li[data-subject='project'] .log-av{background:var(--purple-soft);color:var(--purple)}
.log>li[data-subject='accounting'] .log-av{background:var(--ok-soft);color:var(--ok-ink)}
.log>li[data-subject='mail'] .log-av{background:var(--info-soft);color:var(--info-ink)}
.log>li[data-subject='account'] .log-av{background:var(--teal-soft);color:var(--teal-ink,#0b6b4f)}
.log>li[data-subject='auth'] .log-av{background:var(--warn-soft);color:var(--warn-ink)}
.log>li[data-subject='settings'] .log-av{background:var(--surface-3);color:var(--ink-3)}
.log>li[data-tone='remove'] .log-av{background:var(--bad-soft);color:var(--bad-ink)}
.log>li[data-subject='project'] .log-subject{color:var(--purple)}
.log>li[data-subject='accounting'] .log-subject{color:var(--ok-ink)}
.log>li[data-subject='mail'] .log-subject{color:var(--info-ink)}
.log>li[data-subject='contact'] .log-subject{color:var(--accent-ink)}
.log>li[data-tone='remove'] .log-subject{color:var(--bad-ink)}
/* The activity filter chips: a dot in the subject's colour, so the legend
   above the feed and the discs in it agree. */
.chips a[data-subject]:not([data-subject='all'])::before{content:'';width:7px;height:7px;border-radius:99px;flex:0 0 auto;background:var(--accent)}
.chips a[data-subject='project']::before{background:var(--purple)}
.chips a[data-subject='accounting']::before{background:var(--ok)}
.chips a[data-subject='mail']::before{background:var(--info)}
.chips a[data-subject='account']::before{background:var(--teal)}
.chips a[data-subject='auth']::before{background:var(--warn)}
.chips a[data-subject='settings']::before{background:var(--ink-5)}
.chips a[data-subject='lead']::before{background:var(--pink)}
.log>li[data-subject='lead'] .log-av{background:var(--pink-soft);color:var(--pink)}

/* ── leads ──────────────────────────────────────────────────────────────
   The prospect list and record. Everything below composes the tokens and
   the list grammar above; the two genuinely new objects are the photo grid
   and its lightbox, which the portal had no equivalent of. */

/* The website column: a domain, truncated, in the row's small type. */
.lc-site{width:150px;flex:0 0 auto;font-size:12.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lc-site a{color:var(--ink-3)}
.lc-site a:hover{color:var(--accent-ink)}
@media (max-width:1000px){.lc-site{width:auto}}

/* A group label that is not a <label>: the drop zone and the stored-photo
   grid have no single control to point at. Same face as a label. */
.lead-lbl{display:block;font-size:13px;font-weight:500;color:var(--ink-2);margin:0 0 6px}
.lead-address{font-style:normal;display:grid;gap:2px;font-size:14px;color:var(--ink-2);line-height:1.5}

/* Photo grid: 4:3 tiles, the picture covering each, one focus ring per link.
   is-picker is the edit dialog's copy, where every tile carries a remove
   tick under it instead of opening a lightbox. */
.gallery{list-style:none;margin:0;padding:0;display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}
.gallery li{min-width:0}
.gallery a{display:block;border-radius:var(--r-md);overflow:hidden;border:1px solid var(--line);background:var(--surface-2);aspect-ratio:4/3}
.gallery a img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .2s var(--ease)}
.gallery a:hover img{transform:scale(1.03)}
.gallery a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.gallery.is-picker img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface-2)}
.gallery.is-picker .gallery-remove{margin-top:6px;font-size:12.5px}
@media (prefers-reduced-motion:reduce){.gallery a img{transition:none}}

/* Lightbox: one picture over the popups' scrim, previous/next at the sides,
   the count underneath. Built by portal.js from the gallery's links. */
.lightbox{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;background:var(--scrim);padding:24px}
.lightbox img{max-width:min(100%,1200px);max-height:calc(100vh - 96px);border-radius:var(--r-md);box-shadow:var(--shadow-lg);background:var(--surface)}
.lightbox button{position:absolute;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;min-height:0;padding:0;
  border:1px solid var(--line);border-radius:99px;background:var(--surface);color:var(--ink);cursor:pointer;box-shadow:var(--shadow-sm)}
.lightbox button:hover{background:var(--surface-2)}
.lightbox button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.lightbox button svg{margin:0}
.lightbox-x{top:16px;right:16px}
.lightbox-prev,.lightbox-next{top:50%;transform:translateY(-50%)}
.lightbox-prev{left:16px}
.lightbox-next{right:16px}
.lightbox-prev svg{transform:rotate(180deg)}
.lightbox-count{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);margin:0;padding:4px 12px;border-radius:99px;
  background:var(--surface);color:var(--ink-3);font-size:12.5px;font-variant-numeric:tabular-nums;box-shadow:var(--shadow-sm)}
html.has-lightbox{overflow:hidden}

/* A picked picture previews as a thumbnail beside its name in the drop list. */
.drop-list .thumb{width:40px;height:40px;flex:0 0 auto;border-radius:var(--r-sm);object-fit:cover;border:1px solid var(--line);background:var(--surface-2)}

/* Mailbox picker: the unread count sits at the end of the row, like a folder's. */
.mbox-pick button>span:first-of-type{flex:1 1 auto}
.mbox-pick button>.mfold-n{flex:0 0 auto;overflow:visible}

/* ── touch targets, last word ───────────────────────────────────────────
   These live at the END of the sheet on purpose. Every control below is
   styled somewhere above by a selector of equal specificity — .acct-menu
   button sets min-height:0, .theme-opt a 28px box — so an override placed
   with the rest of the responsive rules loses on source order and the
   target silently stays mouse-sized. Grouped here, they win.

   Everything in this block is a control that a thumb has to hit now that
   the drawer is a real destination rather than a rarely-opened overflow:
   44x44 is the floor from the platform's own table. */
@media (max-width:920px){
  .acct-menu a,.acct-menu button{min-height:44px;font-size:var(--fs-small);padding:10px}
  .side .lang-dd summary{min-height:44px;padding:0 10px 0 6px}
  .lang-dd-opt{min-height:44px}
  .side .theme-opt{width:44px;min-height:44px}
  /* The row that opens the workspace/account menu. */
  .side-ws{min-height:64px}

  /* ── page controls ──────────────────────────────────────────────────
     The portal's controls were sized for a pointer: 40px for a button and
     an input, 36px for the compact ones in list strips, toolbars and
     filter bars. All of those are under the 44px floor once the only
     input is a thumb. Raised together rather than per-component so a
     control cannot be missed, and only on touch widths — the desktop
     rail and its denser toolbars keep their 36/40px proportions. */
  button,input,select,textarea,.btnlink,.cs-btn{min-height:44px}
  /* The compact variants, named explicitly because each sets its own
     min-height later in the sheet than the base rule above. */
  .fbar-form input[type='search'],.fbar-form .cs-btn,.fbar-form button,
  .actpanel-save button,.actpanel-row input,.actpanel-row select,
  .actpanel-row .cs,.actpanel-row button,.actionbar button,
  .lstrip-right button.ghost,.lstrip-right select,.lstrip-right .cs-btn,
  .lsearch input,.mfold.as-btn{min-height:44px}
  /* An icon-only button is square: 44 wide as well as tall. */
  .iconbtn,.row-icon,.dlg-x{min-width:44px;min-height:44px}
  /* ── list rows ──────────────────────────────────────────────────────
     A row is the portal's densest touch surface: a title that opens the
     record, an overflow menu at the trailing end, and the menu's own
     items. All three were pointer-sized. */
  /* The row title. It is an inline link inside .nm, so it cannot become a
     44px box without breaking the line — instead the padding widens the
     strike area vertically while it stays in flow. */
  .crow .nm a,.clist .nm a{display:inline-block;padding-block:8px}
  /* The trailing overflow trigger, and the items it reveals. */
  .rowmenu>summary{min-width:44px;min-height:44px}
  .rowmenu-panel a,.rowmenu-panel button{min-height:44px;display:flex;align-items:center}
  /* Everything else inline inside a card. The tab bar is excluded: its
     links already own a 52px box, and the extra padding pushed the bar to
     81px and started ellipsising the labels at 320px. */
  .card a:not(.btnlink):not(.stat):not(.crow a),
  .clist a:not(.btnlink){padding-block:6px}
  .tabbar a{padding-block:6px 4px}
}
