/* ==========================================================================
   Effred ecosystem — design system
   --------------------------------------------------------------------------
   One shell for every portal of Effred One: a strip of navigation, a rail,
   a dense data grid, Google Sans Flex with Google Sans Code for codes, one
   light theme. Flat surfaces, hairline borders, small radii and quiet
   shadows: the page is made of type and tables, not of decoration.

   Labels are short on purpose. A column is "Joined", not "Date of joining".
   Anything longer than two words belongs in a tooltip, not on the screen.

   Every time on screen is India Standard Time.
   ========================================================================== */

/* -- Light (default) ------------------------------------------------------
   One palette, retuned. The product used to be blue on grey; it is now green
   on a soft sage ground, which is the one change that reaches all 117 screens
   without any of them being edited — every part of the kit reads its colour
   from here rather than carrying its own.

   Two rules survived the retune unchanged, because both are about legibility
   rather than taste: the semantic colours are TEXT colours and are dark
   enough for a 9 px pill to clear 4.5:1 on its own tint, and the graph tones
   are a second, brighter set for marks that only need 3:1. Never swap one for
   the other.
   -------------------------------------------------------------------------- */
:root{
  /* surfaces. --bg is the page, --bg2 every card on it. The page is tinted
     and the card is white, which is what gives a screen of cards its edges
     without a border having to do all the work. */
  --bg:#F1F4F2; --bg2:#fff; --bg3:#EAEFEC; --bgH:#E1E8E4; --bgI:#F7F9F8;
  --bd:#DDE4E0; --bdL:#EBF0ED;
  /* The edge of a control - an input, a select, a secondary button. A
     hairline that is right for a card is too faint to find a field by. */
  --bdS:#C8D2CD;
  /* ink */
  --tx:#16261F; --tx2:#3C4A44;
  /* Muted text. #64756D is what the new palette started at and it cleared
     4.5:1 on white and 4.17:1 on the tinted card ground — which is where
     most of it actually sits: every .ki-sub, .cd-s, .hint and .agd-s in
     the product is muted text on --bg3 or on the page. Two steps darker
     clears 4.5:1 against all four surfaces the kit puts it on. */
  --tx3:#5A6B63;
  /* Brand and semantics. These are TEXT colours — on a 9 px status pill they
     have to clear 4.5:1 against their own tint, which is why the greens and
     ambers are darker here than the portal accents below. */
  --ac:#0E7A5C; --acBg:#E3F0EA; --acD:#0A5C46;
  --gn:#12704F; --gnBg:#E4F1EA;
  --am:#8A5206; --amBg:#FCEFDF;
  --rd:#AF3418; --rdBg:#FBEAE4;
  --bl:#1F5F9E; --blBg:#E9F1F8;
  --vi:#5744BC; --viBg:#EFEDFB;
  --te:#0A6E72; --teBg:#E2F1F1;
  --or:#A0521B; --orBg:#FBEEE3;
  --sl:#44564F; --slBg:#E9EEEB;
  /* Graph tones. Also GRAPHIC — a 3 px bar, a 2 px line, an arc. The text
     tones above are dark because a 9 px label on a tint has to clear 4.5:1;
     a chart drawn in them looks like mud, so these are the same hues at the
     saturation a chart wants. Never use one of these for text. */
  --g-gn:#12996F; --g-rd:#E4572E; --g-am:#D98324; --g-bl:#2F6FB8;
  --g-vi:#6C5CE0; --g-te:#0E9AA0; --g-gy:#9EAAA4;
  /* Portal accents. These are GRAPHIC colours — icon strokes and 3 px rails,
     which need 3:1, not 4.5:1. Keeping them vivid is what stops the seven
     portals from turning into seven shades of the house green. */
  --p-dash:#0E7A5C; --p-ems:#0E9AA0; --p-hrms:#5B58D6; --p-acct:#12996F;
  --p-docs:#B98311; --p-amc:#DD6B20; --p-legal:#7358CC; --p-admin:#44564F;
  --p-vend:#2F6FB8;
  /* shape. Three steps and no more: 6 on a control, 8 on a menu or a tile,
     10 on a card or a dialog. Anything rounder read as a toy. */
  --r:6px; --rl:8px; --rx:10px; --rp:999px;
  /* Shadows are tinted with the ink rather than pure black, and they are
     quiet: the border draws the edge, the shadow only lifts what floats. */
  --sh:0 1px 1px rgba(22,38,31,.04);
  --shM:0 2px 8px rgba(22,38,31,.06),0 1px 2px rgba(22,38,31,.04);
  --shL:0 12px 32px rgba(22,38,31,.12),0 2px 6px rgba(22,38,31,.05);
  --ring:0 0 0 3px var(--acBg);
  /* type. Google Sans Flex is a variable face with an optical-size axis.
     Left on auto it draws 11 px text wider and sturdier than 24 px text,
     so small sizes need no tracking of their own and only display sizes
     are drawn in. The scale: 0 at 14 px and under, then three steps.
     `GSF Fallback` and `GSC Fallback` are local faces resized to the web
     faces' own metrics (declared under this block), so the page does not
     jump when the web font lands. */
  --f:'Google Sans Flex','Google Sans','GSF Fallback',system-ui,-apple-system,'Segoe UI',sans-serif;
  --fm:'Google Sans Code','JetBrains Mono','GSC Fallback',ui-monospace,Consolas,monospace;
  --ls-t:-.005em;  /* a title, 15 to 17 px */
  --ls-h:-.012em;  /* a heading, 18 to 24 px */
  --ls-d:-.02em;   /* display type, 26 px and up */
  /* A large figure. Tabular digits sit wide in this face, so a value from
     21 px up is drawn in a step further than words of the same size. */
  --ls-n:-.02em;
  /* Weights are still 600 / 500 / 400. The face gains stroke at small
     optical sizes, so two roles take the step between: a card's own
     title, and a figure in a table column. */
  --w-t:550; --w-n:450;
  --nav-h:56px;
}

/* -- Fallback faces -------------------------------------------------------
   What the page is set in for the moment before the web font arrives, and
   for good where it never does. A local face, scaled to Google Sans Flex's
   own width at body sizes and given its ascent and descent, so a line of
   text takes the same room either way and nothing below it moves.

   Measured, not guessed: at 13 px the web face is 8.6% wider than Segoe UI
   and 7.8% wider than Arial, and 10% wider at 11 and 12 px, so 109%. Its
   ascent is .97 and its descent .29 of the em with no line gap; an
   override is a share of the ADJUSTED size, hence .97 / 1.09 and
   .29 / 1.09. Two weights, because one local file stretched to 600 is a
   smeared bold. The mono is the same sum over Consolas, whose advance is
   .55 em against Google Sans Code's .6; every other system mono is
   already .6 and needs nothing. */
@font-face{font-family:'GSF Fallback';font-style:normal;font-weight:400 499;
  src:local('Segoe UI'),local('Roboto'),local('Helvetica Neue'),local('Arial');
  size-adjust:109%;ascent-override:89%;descent-override:26.6%;line-gap-override:0%}
@font-face{font-family:'GSF Fallback';font-style:normal;font-weight:500 700;
  src:local('Segoe UI Semibold'),local('Roboto Medium'),
    local('Helvetica Neue Medium'),local('Arial Bold');
  size-adjust:109%;ascent-override:89%;descent-override:26.6%;line-gap-override:0%}
@font-face{font-family:'GSC Fallback';font-style:normal;font-weight:400 500;
  src:local('Consolas');
  size-adjust:109.1%;ascent-override:88.9%;descent-override:26.6%;line-gap-override:0%}


/* -- Base ----------------------------------------------------------------- */
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{font-family:var(--f);background:var(--bg);color:var(--tx);font-size:13px;
  min-height:100vh;-webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  /* Figures line up in a column. Every screen in this product is a column of
     numbers, and proportional digits make a total look ragged. */
  font-variant-numeric:tabular-nums;
  /* The optical-size axis follows the type size by itself: small text is
     drawn open and sturdy, a headline tight. Never pin it. A code
     somebody types back - an IFSC, a PAN, a UTR - goes in .mono, where a
     `1`, an `l` and an `I` are three shapes and the zero is slashed; a
     code in a table column stays in this face (`td.mono`), and money is
     never mono. */
  font-optical-sizing:auto;
  line-height:1.5;text-rendering:optimizeLegibility}
::selection{background:var(--ac);color:var(--acTx,#fff)}
a{color:var(--ac);text-decoration:none}
a:hover{text-decoration:underline}
/* A control does not inherit the page's face: the browser gives a button,
   a select and a file picker its own system font, with proportional
   figures. A chip or a tab written as a <button> with no font of its own
   was therefore set in Arial beside its neighbours. Family and figures
   only - a size here would move every control in the product. */
button,input,select,textarea,optgroup{font-family:inherit;font-variant-numeric:inherit}
h1,h2{line-height:1.25;letter-spacing:var(--ls-h);font-weight:600}
h3,h4{line-height:1.25;letter-spacing:var(--ls-t);font-weight:600}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--bd);border-radius:5px}
::-webkit-scrollbar-thumb:hover{background:var(--tx3)}
/* The ring is the readable shade of the brand, never the brand itself: any
   colour is accepted as a brand now, and a pale one as a focus ring is one
   nobody can find. */
:focus-visible{outline:2px solid var(--acD);outline-offset:1px}
svg.i{width:14px;height:14px;flex-shrink:0;stroke:currentColor;fill:none;
  stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.btn svg.i{width:13px;height:13px}
.ico-btn svg.i{width:13px;height:13px}
.tab svg.i{width:13px;height:13px}
.empty svg.i{width:24px;height:24px}
.pc-ic svg.i{width:19px;height:19px;stroke-width:1.7}
.ki-ic svg.i{width:15px;height:15px}

/* Density is a user preference; it only ever changes padding, never type. */
body[data-density="compact"] table.dt td{padding:4px 9px}
body[data-density="relaxed"] table.dt td{padding:10px 12px}

/* == 1. Load strip + nav circle ============================================
   Two views of one state. The strip answers "is something happening"; the
   circle in the nav answers "is it still happening" once the strip has run
   to 90% and parked there. */
#loadbar{position:fixed;top:0;left:0;height:2px;width:0;z-index:2000;
  background:var(--ac);opacity:1;
  transition:width .25s cubic-bezier(.2,.7,.3,1),opacity .35s}
#loadbar.done{opacity:0}
.navspin{width:15px;height:15px;border-radius:50%;flex-shrink:0;
  border:1.8px solid var(--bd);border-top-color:var(--ac);
  animation:spin .62s linear infinite;opacity:0;
  transition:opacity .2s;margin:0 2px}
.navspin.on{opacity:1}
@keyframes spin{to{transform:rotate(360deg)}}
.ld-spin{display:inline-block;width:16px;height:16px;border:2px solid var(--bd);
  border-top-color:var(--ac);border-radius:50%;animation:spin .62s linear infinite}
.loader-w{display:flex;align-items:center;justify-content:center;padding:38px;
  gap:9px;color:var(--tx3);font-size:12px;font-weight:500}

/* == 2. Top navigation strip =============================================== */
.nav{position:sticky;top:0;z-index:120;background:var(--bg2);
  border-bottom:1px solid var(--bd)}
.nav-in{display:flex;align-items:center;height:var(--nav-h);padding:0 16px;gap:9px;
  max-width:1860px;margin:0 auto}
.nav-brand{font-weight:600;font-size:15px;letter-spacing:var(--ls-t);white-space:nowrap;
  display:flex;align-items:center;gap:9px;color:var(--tx);flex-shrink:0}
.nav-brand:hover{text-decoration:none;opacity:.82}
.nav-logo{height:28px;width:auto;display:block}
.nav-mark{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;
  background:var(--ac);color:var(--acTx,#fff);font-size:14px;
  font-weight:600;letter-spacing:0;flex-shrink:0}
/* The drawn mark sits a little heavier than a UI icon: at 17 px on a coloured
   tile a 1.9 stroke goes thin and the arms start to disappear. */
.nav-mark svg.i{width:17px;height:17px;stroke-width:2.2}
/* Effred One, drawn from its own file on the two planes that are Effred's:
   the tile and the wordmark together, never retyped. */
.nav-one{height:24px;width:auto;display:block;flex:none}
.nav-plane{font-size:12.5px;font-weight:500;color:var(--tx3);white-space:nowrap;
  letter-spacing:0}

/* == The name lockup =======================================================
   A product name with "by Effred" under it, set small.

   It exists because the two things are not the same claim. "007 AI Agent" is
   what the thing is called; "by Effred" is who stands behind it, and on a
   customer's own portal that second line is the only place the word Effred
   appears at all. Setting them on one line made the maker part of the name;
   stacking them at two different sizes says one is the name and the other is
   the maker, which is what a lockup is for.

   Deliberately not a badge, a pill or a ribbon — it is two lines of type. */
.lk{display:flex;flex-direction:column;justify-content:center;min-width:0;
  line-height:1.05;gap:1px}
.lk-n{font-size:15px;font-weight:600;letter-spacing:var(--ls-t);color:var(--tx);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lk-b{font-size:9px;font-weight:600;letter-spacing:.32px;color:var(--tx3);
  white-space:nowrap}
.lk.sm .lk-n{font-size:13px} .lk.sm .lk-b{font-size:8.5px}
.lk.lg .lk-n{font-size:21px;letter-spacing:var(--ls-h)} .lk.lg .lk-b{font-size:10px}
.sep{width:1px;height:16px;background:var(--bd);flex-shrink:0}
/* The tenant chip. Which company am I inside — always answerable at a glance. */
.nav-tenant{display:flex;align-items:center;gap:6px;padding:3px 8px 3px 4px;
  border:1px solid var(--bd);border-radius:var(--rp);background:var(--bgI);
  font-size:11px;font-weight:500;white-space:nowrap;flex-shrink:0;cursor:pointer;
  color:var(--tx)}
.nav-tenant:hover{border-color:var(--tx3);text-decoration:none}
.nav-tenant .tn-av{width:17px;height:17px;border-radius:50%;display:grid;
  place-items:center;font-size:8px;font-weight:600;color:#fff;background:var(--sl)}
.nav-tenant .tn-host{font-family:var(--fm);font-size:9.5px;color:var(--tx3);font-weight:500}
.nav-tag{font-size:12px;font-weight:500;color:var(--tx3);letter-spacing:0;
  white-space:nowrap;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;
  max-width:260px}
.gap{flex:1;min-width:4px}
/* A page that names no section draws no empty tag, and no rule before it. */
.nav-tag:empty,.sep:has(+ .nav-tag:empty){display:none}

/* Global search sits in the strip, not on the page. Ctrl/Cmd-K focuses it. */
.nav-search{display:flex;align-items:center;gap:8px;padding:0 12px;height:36px;
  border:1px solid var(--bd);border-radius:var(--rl);background:var(--bgI);
  min-width:170px;max-width:420px;flex:1;color:var(--tx3);cursor:text;
  transition:border-color .14s,background .14s}
.nav-search:hover{border-color:var(--ac);background:var(--bg2)}
.nav-search input{flex:1;border:none;outline:none;background:none;font-family:var(--f);
  font-size:12.5px;font-weight:500;color:var(--tx);min-width:0;height:auto;padding:0}
.nav-search input:focus{box-shadow:none;border:none}
.kbd{font-family:var(--fm);font-size:10px;font-weight:500;color:var(--tx3);
  border:1px solid var(--bd);border-bottom-width:2px;border-radius:4px;
  padding:1px 4px;background:var(--bg2);white-space:nowrap}

/* Icon actions: bell, approvals, help. Counts ride on the corner. */
.nav-ico{position:relative;width:34px;height:34px;display:inline-flex;
  align-items:center;justify-content:center;border-radius:var(--rl);
  border:1px solid transparent;background:none;color:var(--tx2);cursor:pointer;
  flex-shrink:0;transition:background .12s,color .12s}
.nav-ico:hover{background:var(--bg3);color:var(--tx);text-decoration:none}
.nav-ico .dot{position:absolute;top:3px;right:3px;min-width:15px;height:15px;
  padding:0 4px;border-radius:var(--rp);background:var(--rd);color:#fff;
  font-size:9.5px;font-weight:600;display:grid;place-items:center;
  border:1.5px solid var(--bg2);line-height:1}
/* One colour for every count in the strip. Three badges in three colours
   read as three kinds of alarm; they are three numbers. */
.nav-ico .dot.am,.nav-ico .dot.bl{background:var(--rd)}
.nav-ico.on{background:var(--bg3);color:var(--tx)}


/* A trial counting down, in the strip.
   -------------------------------------------------------------------------
   Amber for most of the last week and red for the last two days, because the
   difference between "soon" and "now" is the only thing this control has to
   communicate. It is a link, not a banner: it goes to the one screen where
   the renewal actually happens. */
.trial-chip{display:inline-flex;align-items:center;height:28px;padding:0 11px;
  border-radius:var(--r);background:var(--amBg);color:var(--am);
  font-size:11px;font-weight:600;white-space:nowrap;flex-shrink:0;
  border:1px solid color-mix(in srgb,var(--am) 26%,transparent)}
.trial-chip:hover{text-decoration:none;background:var(--am);color:#fff}
.trial-chip.hot{background:var(--rdBg);color:var(--rd);
  border-color:color-mix(in srgb,var(--rd) 30%,transparent)}
.trial-chip.hot:hover{background:var(--rd);color:#fff}
@media(max-width:900px){.trial-chip{display:none}}

/* == 3. Product switcher =================================================== */
.sw{position:relative;flex-shrink:0}
.sw-btn{display:inline-flex;align-items:center;gap:8px;height:34px;padding:0 12px;
  border:1px solid var(--bd);border-radius:var(--r);background:var(--bg2);
  color:var(--tx);font-family:var(--f);font-size:13px;font-weight:500;cursor:pointer;
  white-space:nowrap;transition:background .12s,border-color .12s}
.sw-btn:hover{background:var(--bgI);border-color:var(--bdS)}
.sw-btn .car{width:5px;height:5px;border-right:1.6px solid var(--tx3);
  border-bottom:1.6px solid var(--tx3);transform:translateY(-2px) rotate(45deg)}
.sw.open .sw-btn{border-color:var(--ac);box-shadow:var(--ring)}
/* Wide enough that every product name sits on one line. At 376px the two
   long names wrapped and every card in the column below them sat at a
   different height; the cure is width, not a smaller font. Clamped to the
   viewport on a phone. */
.sw-pop{position:absolute;top:43px;left:0;z-index:300;width:min(660px,calc(100vw - 16px));
  max-width:calc(100vw - 26px);
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  box-shadow:var(--shL);padding:9px;display:none;animation:pop .14s ease-out}
.sw.open .sw-pop{display:block}
/* The nav is its own stacking level, so the popover inside it can never
   rise above something fixed over the page - and a resting assistant bar
   at the top centre sat on the switcher's second column. While the
   switcher is open the whole strip comes forward. */
.nav:has(.sw.open){z-index:320}
/* Eleven products on a 720px laptop ran the popover off the bottom with
   no way to reach the last row. The phone block already capped it. */
.sw-pop{max-height:calc(100vh - 62px);overflow-y:auto;overscroll-behavior:contain}
.sw-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:4px}
/* One product is one ROW, not one anchor: the row holds the link that
   replaces the page and a second control that opens the portal beside it.
   An anchor cannot nest an anchor, so the two are siblings under a
   positioned row and the hover state belongs to the row. */
.sw-r{position:relative;display:flex;align-items:stretch;border-radius:10px;
  border:1px solid transparent;min-width:0}
.sw-r:hover{background:var(--bg3)}
.sw-r.on{background:var(--acBg);border-color:var(--ac)}
.sw-i{display:flex;align-items:center;gap:11px;padding:10px 11px;border-radius:10px;
  cursor:pointer;color:var(--tx);border:1px solid transparent;min-width:0;flex:1}
.sw-r>.sw-i{border:none;border-radius:10px 0 0 10px}
.sw-i:hover{background:var(--bg3);text-decoration:none}
.sw-r>.sw-i:hover{background:none}
.sw-i.on{background:var(--acBg);border-color:var(--ac)}
/* Drawn only on hover and on keyboard focus: a second icon on every row
   at rest is eleven icons competing with the eleven that name the
   products. It keeps a 28px target once it is there. */
.sw-nt{flex:none;width:30px;margin:5px 5px 5px 0;border:none;background:none;
  border-radius:8px;color:var(--tx3);cursor:pointer;display:grid;
  place-items:center;opacity:0;transition:opacity .12s}
.sw-nt svg.i{width:13px;height:13px}
.sw-r:hover .sw-nt,.sw-nt:focus-visible{opacity:1}
.sw-nt:hover{background:var(--bg4,var(--bg3));color:var(--tx)}
@media(hover:none){.sw-nt{opacity:1}}
.sw-i .ic{width:30px;height:30px;border-radius:7px;display:grid;place-items:center;
  color:#fff;flex-shrink:0;background:var(--sl)}
.sw-i > span:not(.ic){min-width:0}
.sw-i .nm{display:block;font-size:12.5px;font-weight:600;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:620px){.sw-grid{grid-template-columns:minmax(0,1fr)}}
/* Was `.sb`, which is also the class on every table's search box — a
   bordered 28px flex row with a 190px minimum. The subtitle inherited all
   of it and rendered as a grey input inside every card in the switcher,
   which is also what forced the popover wider than its content. Two
   components must not share a class name. */
.sw-i .sw-sub{display:block;font-size:11px;color:var(--tx3);font-weight:500;
  margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sw-foot{border-top:1px solid var(--bdL);margin-top:6px;padding:7px 9px 3px;
  font-size:11px;color:var(--tx3);font-weight:500;display:flex;
  justify-content:space-between;align-items:center}
/* Says where the second control on each row goes. The chip that used to
   sit here named a keyboard shortcut nothing binds. */
.sw-hint{font-weight:500;text-align:right;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
@media(max-width:620px){.sw-hint{display:none}}
@keyframes pop{from{opacity:0;transform:translateY(-6px) scale(.985)}}

/* == 4. Profile — the ring =================================================
   This was a seven-stop rainbow conic gradient with a blur behind it that lit
   up on hover and rotated while the session refreshed. It was the one piece of
   pure decoration in the product and it sat in the top right corner of every
   screen, which is the most-looked-at thirty pixels a business application
   has. Six colours that mean nothing, next to a status pill whose colours mean
   everything, teaches people that colour here is ornament.

   It is now a ring in the company's own accent, one colour, still. The company
   colour is already the one thing on the page that identifies whose portal
   this is, so the avatar carries it rather than competing with it. It still
   turns while the session is being refreshed — that is a state, not a
   flourish — and it is still a 2 px inset so the face inside stays a circle. */
.pf{position:relative;flex-shrink:0}
.av-ring{width:30px;height:30px;border-radius:50%;padding:2px;cursor:pointer;
  background:var(--acBg);box-shadow:inset 0 0 0 1.5px var(--ac);
  display:grid;place-items:center;transition:box-shadow .18s;position:relative}
.av-ring:hover{box-shadow:inset 0 0 0 1.5px var(--ac),0 0 0 3px var(--acBg)}
.av-ring.spin{background:conic-gradient(from 0deg,var(--ac) 0deg,
  var(--acBg) 120deg,var(--ac) 360deg);
  animation:ringspin 1.1s linear infinite;box-shadow:none}
@keyframes ringspin{to{transform:rotate(360deg)}}
.av-ring > .av-in{width:100%;height:100%;border-radius:50%;background:var(--bg2);
  padding:1.5px;display:grid;place-items:center}
.av-ring .av-face{width:100%;height:100%;border-radius:50%;object-fit:cover;
  display:grid;place-items:center;font-size:10.5px;font-weight:600;color:#fff;
  background:var(--sl);letter-spacing:0}
.av-ring.sm{width:24px;height:24px}
.av-ring.sm .av-face{font-size:8.5px}
.av-ring.lg{width:48px;height:48px}
.av-ring.lg .av-face{font-size:16px}
.av-ring.xl{width:74px;height:74px;padding:3px}
.av-ring.xl .av-face{font-size:24px}
/* Somebody who is not the signed-in user. No accent — the ring is what says
   "this is you", so a colleague's avatar must not wear it. */
.av-ring.mute{background:var(--bg3);box-shadow:inset 0 0 0 1px var(--bd)}
.av-ring.mute:hover{box-shadow:inset 0 0 0 1px var(--bd)}
.pf-pop{position:absolute;top:38px;right:0;z-index:300;width:270px;
  max-width:calc(100vw - 20px);
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  box-shadow:var(--shL);display:none;overflow:hidden;animation:pop .14s ease-out}
.pf.open .pf-pop{display:block}
.pf-head{padding:12px;display:flex;gap:10px;align-items:center;
  border-bottom:1px solid var(--bdL);background:var(--bgI)}
/* Every child of this row is pinned. The head is 270 px wide and holds a
   48 px avatar, so the text has about 170 px — and a full name is a string
   with spaces in it, which wraps to three lines and pushes the head open,
   while an email address is one unbroken token, which pushes it sideways.
   Both were happening. The block is a flex child with min-width:0, the name
   is one line with an ellipsis, and the address wraps by character. */
.pf-hb{flex:1;min-width:0}
.pf-nm{font-size:12.5px;font-weight:600;line-height:1.3;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.pf-ml{font-size:11.5px;color:var(--tx3);font-weight:400;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-rl{font-size:11px;color:var(--tx3);font-weight:500;margin-top:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-list{padding:5px}
.pf-i{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:var(--r);
  font-size:12.5px;font-weight:500;color:var(--tx);cursor:pointer;min-width:0}
.pf-i > span.lb{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.pf-i:hover{background:var(--bg3);text-decoration:none}
.pf-i.dg{color:var(--rd)}
.pf-i .rt{margin-left:auto;flex:none;font-size:11px;color:var(--tx3);
  font-weight:600;font-variant-numeric:tabular-nums}
/* The Export format menu on a table's toolbar. */
.exd{position:relative}
.exd-p{position:absolute;top:calc(100% + 5px);right:0;z-index:300;width:186px;
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rl);
  box-shadow:var(--shL);padding:5px;display:none}
.exd.open .exd-p{display:block}
.exd-i{display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:var(--r);
  color:var(--tx);font-size:12.5px;font-weight:500;text-decoration:none}
.exd-i:hover{background:var(--bg3);text-decoration:none}
.exd-i > .lb{flex:1;min-width:0}
.exd-i > .rt{flex:none;font-size:11px;color:var(--tx3);font-weight:500;
  font-family:var(--fm)}
.pf-sep{height:1px;background:var(--bdL);margin:5px 0}

/* Avatar stack — teams, panels, watchers. */
.av-stack{display:flex;align-items:center}
.av-stack > *{margin-left:-7px;border:2px solid var(--bg2);border-radius:50%}
.av-stack > *:first-child{margin-left:0}
.av{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  font-size:9px;font-weight:600;color:#fff;background:var(--sl);flex-shrink:0;
  letter-spacing:0}
/* The same disc, holding a photograph instead of initials. object-fit is what
   stops a portrait being squashed into a circle. */
img.av{object-fit:cover;background:var(--bg3)}
.av.sm{width:20px;height:20px;font-size:8px}
.av.lg{width:34px;height:34px;font-size:12px}
.av-more{background:var(--bg3);color:var(--tx2)}

/* == 5. Buttons ============================================================ */
.btn{display:inline-flex;align-items:center;gap:6px;padding:0 12px;height:32px;
  border-radius:var(--r);font-family:var(--f);font-size:12.5px;font-weight:500;
  border:1px solid var(--bdS);background:var(--bg2);color:var(--tx);
  box-shadow:0 1px 0 rgba(22,38,31,.04);
  cursor:pointer;white-space:nowrap;flex-shrink:0;text-decoration:none;
  transition:background .12s,border-color .12s,color .12s}
.btn:hover{background:var(--bgI);text-decoration:none;color:var(--tx);
  border-color:var(--tx3)}
.btn:active{background:var(--bg3)}
/* `hidden` has to beat the component.

   The browser's own [hidden]{display:none} is a USER-AGENT rule, and any
   author display rule outranks it - so `.btn{display:inline-flex}` meant
   `<button class="btn" hidden>` drew, at full size, on every screen that
   toggles a control with el.hidden. Twenty-two of them across seventeen
   templates, including two on the paper editors that both showed at once:
   Adopt on a company that had already adopted, which 409s, and Add on one
   that had not.

   A control that cannot do anything must not be drawn, and `hidden` is the
   plainest way a page says so. It wins here. */
[hidden]{display:none!important}
.btn-p{background:var(--ac);color:var(--acTx,#fff);border-color:var(--ac)}
.btn-p:hover{background:var(--acD);border-color:var(--acD);color:#fff}
.btn-dark{background:var(--tx);color:var(--bg2);border-color:var(--tx)}
.btn-dark:hover{opacity:.86;color:var(--bg2)}
.btn-gn{background:var(--gn);color:#fff;border-color:var(--gn)}
.btn-gn:hover{color:#fff;opacity:.88}
.btn-rd{background:var(--rd);color:#fff;border-color:var(--rd)}
.btn-rd:hover{color:#fff;opacity:.88}
.btn-gh{border-color:transparent;background:none;box-shadow:none}
.btn-gh:hover{background:var(--bg3)}
.btn-sm{height:28px;padding:0 10px;font-size:12px;gap:5px;border-radius:var(--r)}
.btn-lg{height:38px;padding:0 16px;font-size:13.5px;border-radius:var(--r)}
.btn-w{width:100%;justify-content:center}
.btn:disabled,.btn.dis{opacity:.42;cursor:not-allowed;pointer-events:none}
.btn.busy{position:relative;color:transparent!important}
.btn.busy svg.i{visibility:hidden}
.btn.busy::after{content:'';position:absolute;inset:0;margin:auto;width:12px;
  height:12px;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;
  border-radius:50%;animation:spin .6s linear infinite}
.btn:not(.btn-p):not(.btn-dark):not(.btn-gn):not(.btn-rd).busy::after{
  border-color:var(--bd);border-top-color:var(--ac)}
.ico-btn{width:32px;height:32px;display:inline-flex;align-items:center;
  justify-content:center;border:1px solid var(--bdS);border-radius:var(--r);
  background:var(--bg2);color:var(--tx2);cursor:pointer;flex-shrink:0}
.ico-btn:hover{border-color:var(--tx3);color:var(--tx)}
.ico-btn.danger:hover{border-color:var(--rd);color:var(--rd)}
.ico-btn.bare{border-color:transparent;background:none}
.ico-btn.bare:hover{background:var(--bg3)}
.btn-grp{display:inline-flex}
.btn-grp .btn{border-radius:0;margin-left:-1px}
.btn-grp .btn:first-child{border-radius:var(--r) 0 0 var(--r);margin-left:0}
.btn-grp .btn:last-child{border-radius:0 var(--r) var(--r) 0}

/* == 6. Page frame ========================================================= */
.main{max-width:1860px;margin:0 auto;padding:18px 18px 34px}
.main.narrow{max-width:1180px}
/* A form at 840 was two columns of 400, which is narrow for a label above
   an input and cramped for three. 1040 gives three honest columns. */
.main.form{max-width:1040px}
.main.wide{max-width:100%}
/* Optional left rail for portals with many sections. Collapses to icons. */
/* THE SHELL OWNS THE VIEWPORT AND THE CONTENT COLUMN IS THE SCROLLER.

   This was `position:sticky` on the rail, and it was wrong on every SHORT
   page in the product, which is most of them. Sticky is bounded by its
   containing block, and the containing block here is `.shell`, whose height
   is its tallest child - the rail. So on a page whose content is shorter than
   the rail, `.shell` is EXACTLY as tall as the rail, sticky has zero range,
   and the rail travels up the page with the content like any ordinary block.

   Measured on /admin_users at 1440x820: shell 763px, rail 763px, body
   scrollHeight 862 against a viewport of 820, and the rail's top went 57px to
   15px over the 42px the page could scroll. Those 42px are the nav plus the
   footer, and the footer is a SIBLING of `.shell` rather than inside it.

   It looked correct on a long page, which is where it was verified, and it
   shipped broken everywhere else. "Verified by measurement" is worth nothing
   unless the case that fails is one of the cases measured.

   So the rail is not sticky at all now. The shell is given the viewport below
   the nav, the rail is given the whole of that height, and the content column
   - `.scr` - is the only thing that scrolls. A rail outside the scrolling box
   cannot move by one pixel at any content length, which is what was asked
   for. It also means the page never scrolls twice: the footer moved INSIDE
   `.scr` (see the four base templates), so nothing is left below the fold for
   the window to scroll down to.

   Below 1024px all of this is released again, in section 26, because there
   the rail is an off-canvas drawer and the window is the right scroller. That
   also keeps `100vh` away from the phone, where `body{zoom}` makes it
   treacherous - a viewport unit does not read the zoom, so a vh box under one
   renders out by the zoom factor. */
.shell{display:flex;align-items:stretch;gap:0;max-width:1860px;margin:0 auto;
  height:calc(100vh - var(--nav-h) - 1px)}
/* The content column, and the one scroller on the page. `min-width:0` is not
   optional: a flex item floors at min-content, so one wide table inside it
   would push the rail off the left edge instead of scrolling sideways.
   No `overscroll-behavior` on purpose - standard chaining is right, and
   containment on a scroll box is what once made every deck card on My space
   a scroll boundary and stopped the page moving under the cursor. */
.scr{flex:1;min-width:0;height:100%;overflow-y:auto}
/* The gutter between the rail and the page. It used to hang off
   `.side + .main`, which stopped matching once the column wrapped them. */
.scr > .main{padding-left:20px}
/* THE STRIP ABOVE THE NAV. `EF.shell` draws `.imp` - the support view and
   impersonation - as a sibling ABOVE the nav, from the KIT and not from any
   template, so grepping the four bases for it finds nothing and it is there
   all the same. It sits in the flow, so a shell sized against the nav alone
   overhangs the glass by the strip's height, the window scrolls by exactly
   that, and the rail travels with it - which is the whole fault this section
   exists to remove, in the one mode where an Effred operator is standing
   inside a customer's portal. Measured without this rule on /admin_users at
   1440x820: a 39px strip, 39px of window scroll, 38.7px of rail movement.

   With a strip present the page becomes a column and the shell takes what is
   LEFT, so the strip's height never has to be written down anywhere - which
   matters because it is one line at 1440 and can be two on a long tenant
   name. Only a page that actually draws one is touched. Below 1024 section
   26 releases all of it, and `@media print` releases it again. */
@media (min-width:1024px){
  body:has(> .imp){display:flex;flex-direction:column;height:100vh}
  /* `width:100%` is not decoration. `.shell` carries `margin:0 auto`, and an
     auto margin on a flex item outranks `stretch` - so in a column flex body
     the shell sized itself to MAX-CONTENT and hung 200px off the right edge,
     which put a horizontal scrollbar on the document, which took 9px off the
     visible height, which made the 100vh body scroll by 9px and the rail move
     again. Measured at 1024x700: shell 1224 wide against a 1015 client. */
  body:has(> .imp) > .shell{height:auto;flex:1;min-height:0;width:100%}
}
/* The rail is a column, so it is drawn as one: a hairline down its right
   edge, a little more width, and its own quiet ground. Without the line it
   floated in the page and the eye had to find the boundary from the ragged
   right-hand ends of the labels. */
/* The rail is static and scrolls on its own.

   It takes the whole height of the shell, which is the whole viewport below
   the nav, and it is NOT inside the scrolling box - so it does not move when
   the content does, at any content length. It was `position:sticky`, and the
   note above `.shell` is why that could never hold on a short page.

   Its own overflow is `auto` and its scrollbar is hidden. A 6 px track down
   the left of every screen is a second vertical line beside the border that
   is already there, and on the twenty screens whose rail fits without
   scrolling it was a groove drawn for nothing. Scrolling still works — wheel,
   trackpad, keyboard and touch are all untouched; only the gutter is gone. */
.side{width:232px;flex-shrink:0;padding:14px 11px 30px;
  height:100%;overflow-y:auto;
  /* No overscroll containment: with it, a wheel over the rail at the foot
     of a page nudged the rail's own rows up a few pixels instead of doing
     nothing — the rail should sit still unless it genuinely overflows. */
  background:var(--bg2);border-right:1px solid var(--bd);scrollbar-width:none;
  -ms-overflow-style:none}
.side::-webkit-scrollbar{width:0;height:0;display:none}
.side.mini{width:58px;padding:14px 8px 30px}
.side-t{font-size:11.5px;font-weight:500;color:var(--tx3);
  letter-spacing:0;padding:16px 10px 6px;line-height:1}
.side-t:first-child{padding-top:4px}
.side.mini .side-t,.side.mini .sd-lb,.side.mini .sd-ct{display:none}
.side.mini .sd{justify-content:center;padding:8px 0}
/* 500 for a label, 600 for the one you are on. It was the other way round —
   every row you were NOT on rendered heavier than the row you were, so the
   rail read as a list of ten equally-shouted destinations with one quiet one.
   The house rule is 600 for titles and values, 500 for labels. */
.sd{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:var(--r);
  font-size:13px;font-weight:500;color:var(--tx2);cursor:pointer;
  margin-bottom:2px;position:relative;letter-spacing:0;
  transition:background .12s,color .12s}
.sd .ic{display:flex;align-items:center;color:var(--tx3);flex-shrink:0}
.sd:hover{background:var(--bg3);color:var(--tx);text-decoration:none}
.sd:hover .ic{color:var(--tx2)}
.sd.on{background:var(--acBg);color:var(--acD);font-weight:600}
.sd.on .ic{color:var(--ac)}
.sd-lb{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sd-ct{font-size:10px;font-weight:600;color:var(--tx2);background:var(--bg3);
  border-radius:var(--rp);padding:1.5px 7px;flex-shrink:0;
  font-variant-numeric:tabular-nums}
.sd:hover .sd-ct{background:var(--bg2)}
.sd.on .sd-ct{background:var(--bg2);color:var(--ac)}
.sd-ct.hot{background:var(--rdBg);color:var(--rd)}
/* The fold at the foot of the rail. Folded, a row is its icon and the label
   floats out on hover — the same fact, shown on demand instead of always. */
.side-min{display:flex;align-items:center;gap:10px;width:100%;margin-top:12px;text-align:left;
  padding:7px 10px;border:0;background:none;border-radius:var(--r);
  color:var(--tx3);font-family:var(--f);font-size:12.5px;font-weight:500;
  cursor:pointer;letter-spacing:0}
.side-min:hover{background:var(--bg3);color:var(--tx)}
.side-min .ic{display:flex;align-items:center;flex-shrink:0}
.side.mini .side-min{justify-content:center;padding:8.5px 0}
.side.mini .side-min .ic svg.i{transform:rotate(180deg)}
.side.mini .sd{position:relative}
.side.mini .sd:hover .sd-lb{display:block;position:absolute;
  left:calc(100% + 9px);top:50%;transform:translateY(-50%);
  background:var(--tx);color:var(--bg2);font-size:11px;font-weight:500;
  padding:4px 10px;border-radius:7px;white-space:nowrap;z-index:60;
  overflow:visible;pointer-events:none}
/* The two-sided rail's switch, above the rows it filters. A segmented pair
   rather than a select: there are exactly two and both should be readable
   without opening anything. It sits inside the rail rather than in the nav
   because it changes the rail and nothing else, and a control belongs
   beside what it acts on. */
.side-sw{display:flex;gap:2px;padding:3px;margin:0 0 10px;border-radius:9px;
  background:var(--bg3)}
.side-sw-b{flex:1;min-width:0;border:none;background:none;cursor:pointer;
  font-family:var(--f);font-size:11px;font-weight:600;color:var(--tx3);
  padding:6px 4px;border-radius:7px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;transition:background .12s,color .12s}
.side-sw-b:hover{color:var(--tx2)}
.side-sw-b.on{background:var(--bg2);color:var(--tx);box-shadow:var(--sh)}
/* Folded to icons there is no room for words, and the rail says which side
   it is on by what it draws. */
.side.mini .side-sw{display:none}
@media (max-width:1023px){.side-min{display:none}
  .side.mini{width:100%;padding:14px 11px 30px}
  .side.mini .side-sw{display:flex}
  .side.mini .side-t,.side.mini .sd-lb,.side.mini .sd-ct{display:revert}}
.side + .main{flex:1;min-width:0;padding-left:20px}
/* The narrow-screen rail lives in section 26 with the rest of the responsive
   rules, so there is one place that decides what happens below 1023px rather
   than two that fight over it. */

/* Page header: breadcrumb, title, status, meta, actions. */
.ph{display:flex;align-items:flex-start;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.ph-l{flex:1;min-width:220px}
.crumb{display:flex;align-items:center;gap:5px;font-size:12px;font-weight:500;
  color:var(--tx3);margin-bottom:4px;flex-wrap:wrap}
.crumb a{color:var(--tx3)}
.crumb a:hover{color:var(--tx2);text-decoration:none}
.crumb .cs{opacity:.5}
.ph h1{font-size:20px;font-weight:600;letter-spacing:var(--ls-h);display:flex;
  align-items:center;gap:9px;flex-wrap:wrap}
.ph-meta{font-size:12.5px;color:var(--tx3);font-weight:400;margin-top:4px;
  display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.ph-meta .mono{font-family:var(--f)}
.ph-act{display:flex;align-items:center;gap:6px;flex-wrap:wrap}

/* == 7. Portal cards — the dashboard's front door ==========================
   A card is a door, not a report. No coloured rail down the edge and no
   blinking dot: the accent lives in the icon tile alone, and anything waiting
   is said in words with a count. Colour is used once per card, quietly. */
.pgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:14px}
@media(max-width:1400px){.pgrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:1040px){.pgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.pgrid{grid-template-columns:minmax(0,1fr)}}
.pc{position:relative;background:var(--bg2);border:1px solid var(--bd);
  border-radius:14px;padding:16px 17px 14px;box-shadow:var(--sh);
  cursor:pointer;overflow:hidden;display:flex;flex-direction:column;
  min-height:158px;text-align:left;font-family:var(--f);color:var(--tx);
  transition:border-color .18s,box-shadow .18s,transform .18s}
.pc:hover{border-color:var(--pa,var(--ac));box-shadow:var(--shM);
  transform:translateY(-1px);text-decoration:none}
.pc:active{transform:none}
.pc-top{display:flex;align-items:flex-start;gap:12px;margin-bottom:14px}
/* The one place the portal's colour appears. A soft tint, a 1 px keyline of
   the same hue, and the icon stroked in it. */
.pc-ic{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;
  color:var(--pa,var(--ac));
  background:color-mix(in srgb,var(--pa,var(--ac)) 9%,transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--pa,var(--ac)) 18%,transparent);
  flex-shrink:0}
@media(min-width:641px){.pc-top > div{min-height:52px}}
.pc-nm{font-size:13px;font-weight:600;letter-spacing:0;line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pc-sb{font-size:10.5px;color:var(--tx3);font-weight:400;margin-top:3px;line-height:1.4;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pc-go{margin-left:auto;color:var(--tx3);opacity:0;flex-shrink:0;
  transition:opacity .18s,transform .18s;transform:translateX(-4px)}
.pc:hover .pc-go{opacity:.8;transform:none}
.pc-nums{display:flex;gap:20px;padding-top:4px;margin-bottom:14px}
.pc-n{min-width:0}
.pc-n-v{font-size:21px;font-weight:600;letter-spacing:var(--ls-n);line-height:1;
  font-variant-numeric:tabular-nums}
.pc-n-l{font-size:11px;font-weight:500;color:var(--tx3);margin-top:5px;
  white-space:nowrap}
.pc-n.hot .pc-n-v{color:var(--rd)}
.pc-n.warn .pc-n-v{color:var(--am)}
.pc-n.ok .pc-n-v{color:var(--gn)}
/* What is waiting. A count and a noun, on a quiet keyline. Never animated --
   a pulsing dot on eight cards at once is a fairground, not a dashboard. */
.pc-need{margin:auto -17px -14px;padding:9px 17px;border-top:1px solid var(--bdL);
  font-size:10.5px;font-weight:500;color:var(--tx2);display:flex;
  align-items:center;gap:7px}
.pc-need .ct{font-weight:600;color:var(--tx);font-variant-numeric:tabular-nums}
.pc-need.hot{color:var(--rd)}
.pc-need.hot .ct{color:var(--rd)}
.pc-need.warn{color:var(--am)}
.pc-need.warn .ct{color:var(--am)}
.pc-need.calm{color:var(--tx3)}
/* Entitled to the company, but not to this person. */
.pc.lock{cursor:not-allowed;opacity:.6;background:var(--bgI)}
.pc.lock:hover{transform:none;box-shadow:var(--sh);border-color:var(--bd)}
.pc.lock .pc-ic{color:var(--tx3);background:var(--bg3);box-shadow:none}
.pc.lock .pc-nums{visibility:hidden}
.pc-lockchip{position:absolute;top:16px;right:16px;display:inline-flex;
  align-items:center;gap:5px;font-size:9px;font-weight:500;
  letter-spacing:.3px;color:var(--tx3)}
/* Portal accent binding */
.pc[data-p="dash"]{--pa:var(--p-dash)} .pc[data-p="ems"]{--pa:var(--p-ems)}
.pc[data-p="hrms"]{--pa:var(--p-hrms)} .pc[data-p="acct"]{--pa:var(--p-acct)}
.pc[data-p="docs"]{--pa:var(--p-docs)} .pc[data-p="amc"]{--pa:var(--p-amc)}
.pc[data-p="legal"]{--pa:var(--p-legal)} .pc[data-p="admin"]{--pa:var(--p-admin)}
.pc[data-p="vend"]{--pa:var(--p-vend)}
.sw-i[data-p="dash"] .ic{background:var(--p-dash)}
.sw-i[data-p="ems"] .ic{background:var(--p-ems)}
.sw-i[data-p="hrms"] .ic{background:var(--p-hrms)}
.sw-i[data-p="acct"] .ic{background:var(--p-acct)}
.sw-i[data-p="docs"] .ic{background:var(--p-docs)}
.sw-i[data-p="amc"] .ic{background:var(--p-amc)}
.sw-i[data-p="legal"] .ic{background:var(--p-legal)}
.sw-i[data-p="admin"] .ic{background:var(--p-admin)}
.sw-i[data-p="vend"] .ic{background:var(--p-vend)}

/* == 8. KPI tiles ========================================================== */
.kg{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:11px;margin-bottom:13px}
.kg.k6{grid-template-columns:repeat(6,minmax(0,1fr))}
.kg.k5{grid-template-columns:repeat(5,minmax(0,1fr))}
.kg.k4{grid-template-columns:repeat(4,minmax(0,1fr))}
.kg.k3{grid-template-columns:repeat(3,minmax(0,1fr))}
/* Two tiles share the row; they were two sixths of it with a hole beside. */
.kg.k2{grid-template-columns:repeat(2,minmax(0,1fr))}
.kg.k1{grid-template-columns:minmax(0,1fr)}
/* Four tiles go to two columns, not three. Three columns of four leaves the
   last one alone in a row beside a hole, and which tile is orphaned changes
   with the screen — the same raggedness §4 rules out for card stacks. Six and
   five still take three, because 3+3 and 3+2 both end level enough. */
@media(max-width:1160px){.kg,.kg.k6,.kg.k5{grid-template-columns:repeat(3,minmax(0,1fr))}
  .kg.k4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.kg,.kg.k6,.kg.k5,.kg.k4,.kg.k3{grid-template-columns:repeat(2,minmax(0,1fr))}}
.ki{background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  padding:14px 16px;box-shadow:var(--sh);position:relative;text-align:left;
  font-family:var(--f);color:var(--tx);display:block;
  transition:border-color .15s,box-shadow .15s}
.ki.drill{cursor:pointer}
.ki.drill:hover{border-color:var(--bdS);box-shadow:var(--shM)}
a.ki:hover,button.ki{text-decoration:none}
button.ki{width:100%;border:1px solid var(--bd);cursor:pointer}

/* A tile carrying a chart is a two-column row: the reading on the left, the
   shape on the right. The chart is `flex:none` and the text `min-width:0`,
   because a long label next to a fixed-width SVG is exactly the shape that
   pushes a card sideways. */
.ki-g{display:flex;align-items:flex-end;gap:12px}
.ki-g .ki-b{flex:1;min-width:0}
.ki-g .ki-c{flex:none;line-height:0}
.ki-c svg.spk{display:block;overflow:visible}
@media(max-width:1060px){
  /* Below this the tile is narrow enough that the chart crowds the figure.
     The figure is the point; the chart goes. */
  .ki-g .ki-c{display:none}
}
.ki-lb{font-size:12px;font-weight:500;color:var(--tx3);
  letter-spacing:0;margin-bottom:6px;display:flex;align-items:center;gap:5px;
  min-width:0}
.ki-lb svg.i{width:12px;height:12px;opacity:.8}
/* The figure carries the tile. It is the one piece of type in the product
   that is allowed to be large, because it is the only one people read from
   across a desk rather than up close. */
.ki-v{font-size:26px;font-weight:600;letter-spacing:var(--ls-n);line-height:1.1;
  font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:6px;
  min-width:0;white-space:nowrap}
/* A long value steps down rather than wrapping. `overflow-wrap:anywhere` was
   right for a label and wrong for a figure: it splits ₹4,79,85,400 across two
   lines mid-number, which is not a number any more. Two steps, because one
   was not enough for a crore with a currency mark in front of it. */
.ki-v.long{font-size:22px;letter-spacing:var(--ls-n)}
.ki-v.xlong{font-size:18px;letter-spacing:-.015em}
.ki-v .un{font-size:12px;font-weight:500;color:var(--tx3);letter-spacing:0}
.ki-v .trend{align-self:center}
.ki-sub{margin-top:6px}
.ki-sub{font-size:11.5px;color:var(--tx3);margin-top:6px;font-weight:400;
  display:flex;align-items:center;gap:5px}
/* Tone reaches the tile, not only the figure.
   -------------------------------------------------------------------------
   A coloured number on a white tile is a number somebody has to already be
   looking at to notice. These are the same tints the status pills use, which
   is what keeps a green here meaning what a green means everywhere else — and
   the pairing is already proved: --gn on --gnBg clears 4.5:1.

   The strength is deliberately not uniform. A tile that is *fine* gets the
   faintest wash there is, enough to give a row of six some warmth and depth;
   a tile that wants somebody gets the full tint. A dashboard where every tile
   is coloured equally is a dashboard where the colour has stopped saying
   anything, which is the failure mode this is avoiding rather than the effect
   it is going for. */
.ki.ok .ki-v{color:var(--gn)} .ki.warn .ki-v{color:var(--am)}
.ki.crit .ki-v{color:var(--rd)} .ki.acc .ki-v{color:var(--ac)}
.ki.info .ki-v{color:var(--bl)} .ki.vi .ki-v{color:var(--vi)}
.ki.te .ki-v{color:var(--te)} .ki.or .ki-v{color:var(--or)}
/* The tile stays white, and its colour arrives as a chip.

   A tinted card and a tinted chip are not the same claim. A whole card washed
   in amber says "this one is a problem"; a 30 px amber square holding a wallet
   says "this one is about money". A home screen has four tiles that are all
   perfectly fine and still want telling apart at a glance, so identity is
   carried by the chip and the card is left alone — which also keeps a genuine
   warning legible, because it is then the only tinted card in the row.

   So: `.ki-ic` is always coloured, and the two backgrounds below are still
   reserved for a tile that actually wants somebody. */
.ki.warn{border-color:color-mix(in srgb,var(--am) 34%,var(--bd))}
.ki.crit{border-color:color-mix(in srgb,var(--rd) 34%,var(--bd))}

/* The chip. Same 30 px rounded square the task rows and the date chips use,
   so a screen of cards has one shape for "an icon that means something". */
.ki-ic{width:30px;height:30px;border-radius:var(--r);flex:none;display:grid;
  place-items:center;background:var(--bg3);color:var(--tx2);margin-bottom:10px}
.ki-ic svg.i{width:15px;height:15px;opacity:1}
.ki.ok .ki-ic{background:var(--gnBg);color:var(--gn)}
.ki.acc .ki-ic{background:var(--acBg);color:var(--ac)}
.ki.info .ki-ic{background:var(--blBg);color:var(--bl)}
.ki.vi .ki-ic{background:var(--viBg);color:var(--vi)}
.ki.te .ki-ic{background:var(--teBg);color:var(--te)}
.ki.or .ki-ic{background:var(--orBg);color:var(--or)}
.ki.warn .ki-ic{background:var(--bg2);color:var(--am)}
.ki.crit .ki-ic{background:var(--bg2);color:var(--rd)}
/* With a chip above it the label no longer carries an icon of its own. */
.ki-ic + .ki-lb svg.i{display:none}
/* No rail down the edge. A 3 px coloured bar on a tinted tile is the second
   time the same fact is said, and six of them in a row is a ribbon — which is
   the one piece of decoration §4 rules out by name. The tint carries the
   tone; the figure carries the reading. */
/* An arrow, and nothing else. It used to carry a number as well, which is
   the same number the sub-line under it already says in words — "+12" above
   "+12 from last week". The arrow answers "which way" at a glance and the
   line answers "by how much, since when"; saying it twice makes the tile
   look like it is shouting. */
.trend{display:inline-flex;align-items:center;font-weight:600;font-size:9px;
  flex:none}
.trend svg.i{width:11px;height:11px;fill:currentColor;stroke:none}
.trend.up{color:var(--g-gn)} .trend.dn{color:var(--g-rd)}
.trend.flat{color:var(--tx3)}

/* == Small charts ==========================================================
   Four shapes with no library behind them. See EF.sparkBars / sparkArea /
   arcGauge / ring — the geometry is in the kit, this is only how they sit. */
.spk{flex:none}
.rng{position:relative;display:inline-grid;place-items:center;flex:none}
.rng svg{position:absolute;inset:0}
.rng-v{position:relative;font-size:12px;font-weight:600;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums}

/* A legend that is a row of words, for a chart small enough not to need a
   box round it. */
.lg2{display:flex;flex-wrap:wrap;gap:5px 13px;margin-top:9px}
.lg2 span{display:inline-flex;align-items:center;gap:5px;font-size:10px;
  font-weight:600;color:var(--tx3)}
.lg2 i{width:7px;height:7px;border-radius:2px;flex:none}

/* == 9. Cards and grids ==================================================== */
.cd{background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  overflow:hidden;box-shadow:var(--sh);margin-bottom:12px}
.cd-h{padding:12px 16px;border-bottom:1px solid var(--bdL);display:flex;
  align-items:center;justify-content:space-between;gap:9px;flex-wrap:wrap}
.cd-t{font-size:14px;font-weight:var(--w-t);letter-spacing:0;display:flex;
  align-items:center;gap:8px}
.cd-s{font-size:12px;color:var(--tx3);font-weight:400}
.cd-bd{padding:16px}
.cd-bd.flush{padding:0}
/* A card whose content sits directly inside it — no .cd-h, no .cd-bd —
   still gets the card's padding. The header/body pair is the contract, but
   a dozen screens predate it, and content flush against overflow:hidden is
   content with its first letter cut off: "IDENTITY" reading "DENTITY" on
   the company page is how this was found. */
.cd:not(:has(> .cd-h)):not(:has(> .cd-bd)){padding:16px}
.cd-f{padding:10px 16px;border-top:1px solid var(--bdL);background:var(--bgI);
  font-size:12px;font-weight:400;color:var(--tx3);display:flex;
  justify-content:space-between;align-items:center;gap:8px}
.g2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:13px;margin-bottom:13px}
/* An odd last child spans, rather than sitting alone in half a row with a
   hole beside it. `:nth-last-child(1):nth-child(odd)` is "the last one, and
   there is an odd number of them". */
.g2 > :last-child:nth-child(odd){grid-column:1 / -1}
.g3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:13px;margin-bottom:13px}
.g21{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:13px;margin-bottom:13px}

/* == A card area that balances itself =====================================
   A dashboard laid out as two grid columns, each holding its own stack of
   cards, is ragged by construction: the two stacks are independent, so one
   ends 260 px above the other and the difference is a hole. Which stack is
   short changes per company — a firm with one department has a 100 px chart
   card, a firm with nine has a 300 px one — so no hand-tuned split is right
   for everybody.

   Flowing them balances instead of being balanced. The browser fills the
   columns to equal height whatever arrives, and `break-inside: avoid` keeps
   a card whole. Cards keep their own order, so the important one is still
   first — first in the left column rather than first on the page.

   Not grid masonry: that is still behind a flag in most browsers, and this
   has done the same job since 2012. */
/* A row of cards that ends level.
   -------------------------------------------------------------------------
   Three cards side by side, each as tall as the tallest — because a row whose
   bottoms are 80 px apart reads as three things that failed to line up rather
   than as one row. The body takes the slack, so every header stays at the top
   of its own card. */
.lvl{align-items:stretch}
.lvl > .cd{display:flex;flex-direction:column;margin-bottom:0}
.lvl > .cd > .cd-bd{flex:1}
/* A card that spans the row is on its own and has nothing to be level with,
   so it keeps its natural height rather than stretching to a row of one. */
.lvl > .cd:last-child:nth-child(odd){display:block}

.cols{columns:2;column-gap:13px;margin-bottom:13px}
.cols > *{break-inside:avoid;-webkit-column-break-inside:avoid;
  page-break-inside:avoid;margin:0 0 13px;display:block;width:100%}
/* `display:block` above beats the browser's own [hidden] rule, so a card a
   screen deliberately did not draw would come back as an empty box. */
.cols > [hidden]{display:none}
.cols3{columns:3}
@media(max-width:1060px){.cols,.cols3{columns:1}}
@media(min-width:1061px) and (max-width:1400px){.cols3{columns:2}}
.g12{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:9px;margin-bottom:9px}
/* `minmax(0,1fr)`, not `1fr`. A bare `1fr` is `minmax(auto,1fr)` and `auto`
   floors at MIN-CONTENT, so one wide child - a table, a long unbroken
   reference - pushes the track past the viewport and the whole page drags
   sideways on a phone. The grid reports itself as collapsed to one column
   the whole time, which is why this reads as a child's problem when it is
   the track's. Zero as the minimum lets the child scroll inside its own
   `.rtw` instead, which is what that class is for. */
@media(max-width:1000px){
  .g2,.g3,.g21,.g12{grid-template-columns:minmax(0,1fr)}}
.chart-wrap{position:relative;height:236px}
.chart-wrap.sm{height:172px}
.chart-wrap.lg{height:310px}

/* == 10. Tabs, segments ==================================================== */
/* Wrap, never clip. The strip used to scroll with the scrollbar hidden, so
   a screen whose tabs outgrew it simply lost the last ones — seven tabs on
   the company page showed five and nothing said so. A second row is ugly
   for a moment; an unreachable tab is broken for ever. */
.tabs{display:flex;flex-wrap:wrap;gap:1px;background:var(--bg3);
  border-radius:var(--rl);padding:3px;margin-bottom:11px;width:max-content;
  max-width:100%}
.tab{border:none;background:none;font-family:var(--f);font-size:12.5px;font-weight:500;
  color:var(--tx2);padding:6px 14px;border-radius:var(--r);cursor:pointer;
  white-space:nowrap;display:flex;align-items:center;gap:6px}
.tab:hover{color:var(--tx)}
.tab.on{background:var(--bg2);color:var(--tx);box-shadow:var(--sh)}
.tab .cnt{background:var(--tx3);color:var(--bg2);border-radius:var(--rp);padding:0 5px;
  font-size:10px;font-weight:600;min-width:15px;text-align:center;line-height:15px}
.tab.on .cnt{background:var(--ac);color:var(--acTx,#fff)}
.tab .cnt.rd{background:var(--rd);color:#fff}
/* Underline tabs for record detail pages. */
.utabs{display:flex;gap:2px;border-bottom:1px solid var(--bd);margin-bottom:12px;
  overflow-x:auto;scrollbar-width:none}
.utabs::-webkit-scrollbar{display:none}
.utab{border:none;background:none;font-family:var(--f);font-size:12.5px;font-weight:500;
  color:var(--tx3);padding:8px 12px;cursor:pointer;white-space:nowrap;
  border-bottom:2px solid transparent;margin-bottom:-1px;display:flex;
  align-items:center;gap:6px}
.utab:hover{color:var(--tx2)}
.utab.on{color:var(--tx);border-bottom-color:var(--ac)}

/* == 11. Toolbar, filters ================================================== */
.toolbar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:8px 12px;
  border-bottom:1px solid var(--bd);background:var(--bg2)}
.sb{display:flex;align-items:center;gap:7px;padding:0 10px;height:32px;
  border:1px solid var(--bdS);border-radius:var(--r);background:var(--bg2);
  min-width:190px;flex:1;max-width:330px}
.sb svg{color:var(--tx3)}
.sb input{flex:1;border:none;outline:none;font-family:var(--f);font-size:12.5px;
  background:none;color:var(--tx);padding:0;min-width:0;height:auto}
.sb input:focus{box-shadow:none;border:none}
.sel{appearance:none;
  background:var(--bg2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%235A6B63'/%3E%3C/svg%3E") no-repeat right 8px center;
  border:1px solid var(--bdS);border-radius:var(--r);padding:0 24px 0 10px;height:32px;
  font-family:var(--f);font-size:12.5px;font-weight:500;color:var(--tx);cursor:pointer;
  width:auto}
option{background:var(--bg2);color:var(--tx)}
.chip{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:500;
  padding:4px 11px;border-radius:var(--rp);background:var(--bg3);color:var(--tx2);
  border:1px solid var(--bd);cursor:pointer;white-space:nowrap}
/* The red is for a chip that removes a filter — the X reading. A chip that
   *selects* one is a different control and must not promise a delete. */
.chip:hover{border-color:var(--rd);color:var(--rd)}
.chip.st{cursor:default} .chip.st:hover{border-color:var(--bd);color:var(--tx2)}
.chip.on{background:var(--acBg);border-color:var(--ac);color:var(--ac)}
.chip.on:hover,.chip-row.pick .chip:hover{border-color:var(--ac);color:var(--ac)}
.chip .n{font-variant-numeric:tabular-nums;opacity:.7;font-weight:600}
.chip-row{display:flex;gap:5px;flex-wrap:wrap;padding:7px 12px;
  border-bottom:1px solid var(--bd);background:var(--bg2);align-items:center}
/* The same row of chips used as a page control rather than a table header:
   no bar, no border, no background. Two screens wanted it, which is the bar
   for putting a shape in the kit rather than in a page. */
.ph-act .chip-row{padding:0;border:0;background:none}
/* Quick-range segment — the control people reach for first. */
.qf{display:inline-flex;background:var(--bg3);border-radius:var(--rl);padding:3px;gap:1px}
.qf button{border:none;background:none;font-family:var(--f);font-size:12px;
  font-weight:500;color:var(--tx2);padding:6px 13px;border-radius:6px;cursor:pointer;
  white-space:nowrap}
.qf button:hover{color:var(--tx)}
.qf button.on{background:var(--bg2);color:var(--tx);box-shadow:var(--sh)}
.qf button.on.crit{color:var(--rd)} .qf button.on.warn{color:var(--am)}
/* Bulk-action bar, appears when rows are selected. */
.bulk{display:flex;align-items:center;gap:8px;padding:7px 12px;background:var(--acBg);
  border-bottom:1px solid var(--ac);font-size:12px;font-weight:500;color:var(--ac);
  flex-wrap:wrap}

/* == 12. Data grid ========================================================= */
.rtw{overflow:auto;max-height:calc(100vh - 290px);min-height:260px;position:relative;
  background:var(--bg2)}
.rtw.short{max-height:340px;min-height:0}
.rtw.auto{max-height:none;min-height:0}
.grid-ov{position:absolute;inset:0;display:none;align-items:center;
  justify-content:center;gap:9px;
  background:color-mix(in srgb,var(--bg2) 74%,transparent);z-index:5;
  font-size:11px;font-weight:500;color:var(--tx2)}
.rtw.loading .grid-ov{display:flex}
table.dt{border-collapse:separate;border-spacing:0;font-size:12.5px;white-space:nowrap;
  width:max-content;min-width:100%}
/* The head is the table's quietest row: sentence case, muted, one rule
   under it. The rows carry no vertical rules - columns are aligned, not
   caged - and the sort arrow and the filter draw on hover or when on. */
table.dt th{position:sticky;top:0;z-index:3;background:var(--bgI);color:var(--tx3);
  font-family:var(--f);font-weight:500;font-size:11.5px;letter-spacing:0;
  padding:9px 8px;text-align:left;border-bottom:1px solid var(--bd)}
table.dt th:has(> .th-in){padding:0}
table.dt th.num{text-align:right}
table.dt th.num .th-in{justify-content:flex-end}
table.dt th.num .th-lb{flex:0 1 auto;order:2}
.th-in{display:flex;align-items:center;gap:5px;padding:9px 8px;cursor:pointer;
  user-select:none;white-space:nowrap}
.th-in:hover{color:var(--tx)}
.th-in.plain{cursor:default}
.th-lb{flex:1;overflow:hidden;text-overflow:ellipsis}
.th-arrow{font-size:8px;opacity:0;transition:opacity .12s}
.th-in:hover .th-arrow{opacity:.5}
.th-arrow.on{opacity:1;color:var(--tx)}
table.dt th:not(:hover):not(:focus-within) .th-flt:not(.on),
table.dt th:not(:hover):not(:focus-within) .th-f:not(.on){opacity:0}
@media(hover:none){.th-arrow{opacity:.4}
  table.dt th:not(:hover):not(:focus-within) .th-flt:not(.on),
  table.dt th:not(:hover):not(:focus-within) .th-f:not(.on){opacity:1}}
.th-f{width:11px;height:11px;flex-shrink:0;cursor:pointer;color:var(--tx3);
  fill:currentColor}
.th-f:hover,.th-f.on{color:var(--ac)}
/* Eight a side, not twelve. The new face's tabular digits are a seventh
   wider than the old one's and its small text a twentieth, and a dozen
   lists that fitted a 1440 or a 1366 screen began to scroll sideways. The
   type stays the size it was; the room comes out of the gutter between
   columns, which is still sixteen. Ten was tried and left five scrolling. */
table.dt td{padding:9px 8px;border-bottom:1px solid var(--bdL);
  color:var(--tx);vertical-align:middle;
  max-width:440px;overflow:hidden;text-overflow:ellipsis}
table.dt td.num{text-align:right;font-weight:var(--w-n);font-variant-numeric:tabular-nums}
table.dt td.mono{font-family:var(--f);font-weight:500}
table.dt tbody tr{cursor:pointer}
table.dt tbody tr:last-child td{border-bottom:0}
table.dt tbody tr:hover td{background:var(--bgI)}
table.dt tbody tr.tbl-on td{background:var(--acBg)}
table.dt tbody tr.mut td{color:var(--tx3)}
table.dt tfoot td{background:var(--bgI);font-weight:600;border-top:1px solid var(--bdS);
  position:sticky;bottom:0;z-index:2}
.sticky-l{position:sticky;left:0;background:var(--bg2);z-index:2;
  border-right:1px solid var(--bd)}
table.dt th.sticky-l{z-index:4;background:var(--bgI)}
table.dt tbody tr:hover .sticky-l{background:var(--bgI)}
table.dt tbody tr.tbl-on .sticky-l{background:var(--acBg)}
.sticky-r{position:sticky;right:0;background:var(--bg2);
  border-left:1px solid var(--bd);z-index:2}
table.dt th.sticky-r{z-index:4;background:var(--bgI)}
table.dt tbody tr:hover .sticky-r{background:var(--bgI)}
table.dt tbody tr.tbl-on .sticky-r{background:var(--acBg)}
.row-act{display:flex;gap:4px;justify-content:flex-end}
.sub{font-size:11px;color:var(--tx3);font-weight:400}
.cbx{accent-color:var(--ac);width:13px;height:13px;cursor:pointer}
/* Two-line identity cell: avatar, name, secondary. Used in every directory. */
.idc{display:flex;align-items:center;gap:8px;min-width:0}
.idc-b{min-width:0}
.idc-n{font-weight:500;font-size:12.5px;overflow:hidden;text-overflow:ellipsis}
.idc-s{font-size:11px;color:var(--tx3);font-weight:400;overflow:hidden;
  text-overflow:ellipsis;margin-top:1px}
/* Number + proportional bar, so magnitude is visible while scanning. */
.dl{display:flex;align-items:center;gap:7px;justify-content:flex-end}
.dl-n{font-weight:500;font-variant-numeric:tabular-nums}
.dl-bar{width:36px;height:4px;border-radius:2px;background:var(--bg3);
  overflow:hidden;flex-shrink:0}
.dl-bar i{display:block;height:100%;border-radius:2px;background:var(--ac)}
/* Column filter popup + column chooser */
.fdd{position:fixed;z-index:400;background:var(--bg2);border:1px solid var(--bd);
  border-radius:9px;box-shadow:var(--shM);min-width:215px;max-width:300px;
  max-height:340px;display:none;flex-direction:column}
.fdd.show{display:flex}
.fdd-h{padding:7px 10px;border-bottom:1px solid var(--bd)}
.fdd-h input{width:100%;padding:0 8px;height:27px;border:1px solid var(--bd);
  border-radius:5px;font-size:10.5px;background:var(--bg);color:var(--tx);outline:none}
.fdd-b{flex:1;overflow-y:auto;padding:4px 0;min-height:60px}
.fdd-i{display:flex;align-items:center;gap:7px;padding:5px 12px;font-size:10.5px;
  cursor:pointer}
.fdd-i:hover{background:var(--bg3)}
.fdd-i input{accent-color:var(--ac);width:13px;height:13px}
.fdd-f{padding:6px 10px;border-top:1px solid var(--bd);display:flex;gap:6px;
  justify-content:flex-end}
.colpick{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:2px}
.colpick label{display:flex;align-items:center;gap:7px;padding:5px 8px;border-radius:5px;
  font-size:11px;cursor:pointer;font-weight:600}
.colpick label:hover{background:var(--bg3)}
.colpick input{accent-color:var(--ac);width:13px;height:13px}

/* -- Column value filters, on every table ---------------------------------- */
.th-flt{border:none;background:none;padding:0 2px;cursor:pointer;
  color:var(--tx3);display:inline-grid;place-items:center;border-radius:4px}
.th-flt .i{width:11px;height:11px}
.th-flt:hover{color:var(--tx)}
.th-flt.on{color:var(--acD)}
.flt-pop{position:fixed;z-index:520;background:var(--bg2);
  border:1px solid var(--bd);border-radius:10px;box-shadow:var(--shL);
  padding:6px;min-width:160px;max-width:260px;max-height:300px;overflow:auto}
.flt-i{display:flex;align-items:center;gap:7px;padding:5px 8px;font-size:11.5px;
  border-radius:6px;cursor:pointer}
.flt-i:hover{background:var(--bg3)}
.flt-i input{accent-color:var(--ac)}
.flt-f{border-top:1px solid var(--bdL);margin-top:4px;padding:6px 4px 2px}

/* == 13. Pagination ======================================================== */
.pgw{display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:7px 12px;border-top:1px solid var(--bd);flex-wrap:wrap;background:var(--bg2)}
.pg-btn{min-width:28px;height:28px;padding:0 9px;border:1px solid var(--bdS);
  border-radius:var(--r);background:var(--bg2);color:var(--tx2);font-size:12px;
  font-weight:500;cursor:pointer}
.pg-btn:hover:not(:disabled){border-color:var(--tx3);color:var(--tx)}
.pg-btn.on{background:var(--ac);color:var(--acTx,#fff);border-color:var(--ac)}
.pg-btn:disabled{opacity:.4;cursor:not-allowed}
.pg-info{font-size:12px;color:var(--tx3);font-weight:400}

/* == 14. Status: tags, dots, pills ========================================= */
.tg{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;
  border-radius:var(--rp);font-size:11px;font-weight:500;white-space:nowrap;
  letter-spacing:0;line-height:1.45}
.tg::before{content:'';width:5px;height:5px;border-radius:50%;background:currentColor;
  flex-shrink:0;opacity:.85}
.tg.nodot::before{display:none}
.tg-gn{background:var(--gnBg);color:var(--gn)} .tg-am{background:var(--amBg);color:var(--am)}
.tg-rd{background:var(--rdBg);color:var(--rd)} .tg-bl{background:var(--blBg);color:var(--bl)}
.tg-vi{background:var(--viBg);color:var(--vi)} .tg-ac{background:var(--acBg);color:var(--ac)}
.tg-te{background:var(--teBg);color:var(--te)} .tg-or{background:var(--orBg);color:var(--or)}
.tg-gy{background:var(--bg3);color:var(--tx2)}
.tg.lg{font-size:12px;padding:3px 10px}
.tg.sq{border-radius:5px}
/* Priority + severity marks */
.pri{display:inline-flex;align-items:center;gap:4px;font-size:9.5px;font-weight:600}
.pri i{width:3px;height:11px;border-radius:2px;background:currentColor;display:block}
.pri.p1{color:var(--rd)} .pri.p2{color:var(--am)} .pri.p3{color:var(--bl)}
.pri.p4{color:var(--tx3)}
/* Progress */
.prg{height:6px;border-radius:4px;background:var(--bg3);overflow:hidden;min-width:52px}
.prg i{display:block;height:100%;border-radius:3px;background:var(--ac);
  transition:width .35s ease-out}
.prg.gn i{background:var(--gn)} .prg.am i{background:var(--am)} .prg.rd i{background:var(--rd)}
.prg.lg{height:8px}

/* == 15. Modals and drawers ================================================ */
.mm{position:fixed;inset:0;z-index:300;background:rgba(14,22,18,.42);display:none;
  align-items:center;justify-content:center;padding:18px}
.mm.show{display:flex}
.md{background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  width:100%;max-width:900px;max-height:calc(100vh - 52px);display:flex;
  /* nowrap said out loud: a wrapped column flex with a bounded height
     puts the FOOTER in a second column at the top-right, outside the
     card — which is exactly where the first phone test found it. */
  flex-direction:column;flex-wrap:nowrap;
  box-shadow:var(--shL);animation:mdin .15s ease-out}
/* Widened across the board. Every dialog in this product is a form, and a
   form dialog at 820 put a two-column row at 380 each with a 9 px gutter,
   which is where a label like Reporting manager wraps and the row goes
   ragged. */
/* Size classes are NAMESPACED. `size:'sm'` used to land the bare class
   `sm` on the dialog — which is also the summary strip component, whose
   flex-wrap:wrap ejected the footer of every small dialog into a second
   column the moment the phone's height cap made the column wrap. The
   repo's oldest trap, found inside the kit itself. */
.md-lg{max-width:1180px} .md-sm{max-width:520px} .md-xl{max-width:1400px}
@keyframes mdin{from{opacity:0;transform:translateY(-10px) scale(.99)}}
.md-h{display:flex;align-items:flex-start;justify-content:space-between;
  padding:16px 20px;border-bottom:1px solid var(--bd);gap:10px}
.md-t{font-size:15px;font-weight:600;letter-spacing:var(--ls-t);display:flex;
  align-items:center;gap:8px}
.md-s{font-size:12px;color:var(--tx3);font-weight:400;margin-top:3px}
.md-x{width:28px;height:28px;display:grid;place-items:center;border:none;
  background:none;color:var(--tx3);cursor:pointer;border-radius:var(--r);flex-shrink:0}
.md-x:hover{color:var(--tx);background:var(--bg3)}
.md-b{flex:1;overflow-y:auto;padding:20px}
.md-b.flush{padding:0}
.md-f{padding:12px 20px;border-top:1px solid var(--bd);display:flex;
  justify-content:flex-end;gap:8px;flex-wrap:wrap;align-items:center}
.md-f .gap{flex:1}
/* Right drawer for quick view / quick edit. */
.dw{position:fixed;inset:0;z-index:300;display:none}
.dw.show{display:block}
.dw-bg{position:absolute;inset:0;background:rgba(14,22,18,.36)}
.dw-p{position:absolute;top:0;right:0;bottom:0;width:min(640px,100%);
  background:var(--bg2);border-left:1px solid var(--bd);display:flex;
  flex-direction:column;box-shadow:var(--shL);animation:dwin .18s ease-out}
/* `drawer()` emits `dw-` + the size it was given, so the class on the
   panel is `.dw-wide` and `.dw-lg` — `.dw-p.wide` matched nothing and
   four screens that asked for a wide panel silently got the narrow one
   from the day the drawer shipped. The size classes are namespaced the
   way the modal's are, for the reason written above `.md-sm`. */
.dw-p.dw-wide,.dw-p.wide{width:min(960px,100%)}
.dw-p.dw-lg{width:min(820px,100%)}
.dw-p.dw-sm{width:min(460px,100%)}
@keyframes dwin{from{transform:translateX(28px);opacity:.4}}

/* == A pane that scrolls itself =============================================
   A dialog and a drawer have always been height-capped with their own body
   scrolling (`.md-b`, `.dw-b` above). An IN-PAGE pane never was — so every
   list-beside-detail screen in this product scrolled the DOCUMENT, and the
   worst of them, vendor onboarding, put two thousand pixels of submitted
   form into a column beside a queue: reading the form scrolled the queue,
   the filter chips and the Approve button off the top of the window, and
   deciding meant scrolling all the way back.

   `.pn` is the missing primitive and it is deliberately two rules, not one.
   The pane is capped to what is left of the viewport under the sticky nav
   and scrolls inside itself; `.pn-b` is the part that scrolls, so a card
   header or a decide bar can sit still above or below it. Both release on a
   phone, where a fixed-height pane inside a page that already scrolls is
   two scrollbars for one hand. */
.pn{max-height:calc(100vh - var(--pn-top,132px));min-height:0;
  display:flex;flex-direction:column;overflow:hidden}
.pn-b{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin}
.pn-b::-webkit-scrollbar{width:7px}
.pn-b::-webkit-scrollbar-thumb{background:var(--bd);border-radius:4px}
.pn-b::-webkit-scrollbar-track{background:transparent}
/* A pane that is the whole card, header included. */
.cd.pn>.cd-bd{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}
@media(max-width:1023px){
  .pn{max-height:none;overflow:visible;display:block}
  .pn-b{overflow:visible;max-height:none}
  .cd.pn>.cd-bd{overflow:visible}
}
/* A pane whose body is one data grid. `.rtw` caps itself at
   `100vh - 290px`, a guess at the chrome above it, and inside a pane that
   guess is a second scrollbar for one hand: measured at 1400px with tiles
   and tabs above the list, the pane body scrolls 39px while the grid
   scrolls the rest, so the search box and the pager slide away under the
   reader. Here the pane owns the height and the grid fills it - one
   scroller, and it is the GRID's, which is what keeps `table.dt th` stuck
   while the rows move. Freeing the cap instead was tried and measured and
   is wrong: the headings stop sticking entirely. Released below 1024 with
   the rest of the pane. */
.pn-g{display:flex;flex-direction:column;min-height:0}
.pn-g>.rtw{max-height:none;min-height:0;flex:1}
@media(max-width:1023px){
  .pn-g{display:block}
  .pn-g>.rtw{max-height:none;flex:none}
}
/* Label/value detail grid. Each fact is its own soft tile rather than a
   cell in a hairline lattice: the lattice doubled its borders against the
   frame, drew a rule under the last row, and left a ragged hole where the
   final row ran short — three faults for the price of drawing lines
   between things that were never a table. */
.dv{display:grid;grid-template-columns:repeat(auto-fill,minmax(238px,1fr));
  gap:9px}
.dv-i{padding:10px 13px;border:1px solid var(--bdL);border-radius:var(--rl);
  background:var(--bgI);min-width:0}
/* A value nobody has filled in. Grey and lighter, so a half-complete record
   reads as gaps to fill rather than as a wall of identical rows. */
.dv-v.none{color:var(--tx3);font-weight:400}
/* The control that asks to change a value sits with it, not in its own
   column — a column of buttons beside a column of facts is a table, and this
   is not one. */
.dv-i .fw{display:flex;align-items:center;gap:8px;min-width:0}
.dv-i .fw .v{flex:1;min-width:0;overflow-wrap:anywhere}
.dv-i .fw .tg,.dv-i .fw .ico-btn{flex:none}
.dv-l{font-size:12px;font-weight:500;color:var(--tx3);
  letter-spacing:0;margin-bottom:4px}
.dv-v{font-size:13.5px;font-weight:500;line-height:1.5;white-space:pre-wrap;
  overflow-wrap:anywhere;word-break:normal;min-height:20px}
.dv-v.mono{font-family:var(--f)}
.dv-i.wide{grid-column:1/-1}
.sec-t{font-size:12.5px;font-weight:600;color:var(--tx2);
  letter-spacing:0;margin:18px 0 8px;display:flex;align-items:center;gap:8px}
.sec-t::after{content:'';flex:1;height:1px;background:var(--bdL)}

/* Facts about one thing: label left, value right, aligned down the column.
   Lives here rather than in a page because a drawer, a profile and a confirm
   box all want the same shape, and three copies drift. */
.kv{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:9px 18px;
  font-size:12.5px;align-items:baseline;margin:0}
.kv dt{color:var(--tx3);white-space:nowrap;font-weight:500}
.kv dd{color:var(--tx);margin:0;min-width:0;overflow-wrap:anywhere;
  font-weight:500}
.kv dd.mono{font-family:var(--f)}
/* `.wide` sets a FLOOR on the label column, not a fixed width.
   -------------------------------------------------------------------------
   It was `104px 1fr`, and `dt` is `white-space:nowrap` — so any label longer
   than 104px at 12 px overflowed its own cell and sat on top of its value.
   "On this band since" and "Last promoted" both do, which is why the profile
   read as two columns that had come apart.

   `minmax(104px, max-content)` keeps short lists lining up at a common width,
   which is the whole reason the modifier exists, and lets a long label push
   the column out rather than spill over it. */
.kv.wide{grid-template-columns:minmax(104px,max-content) minmax(0,1fr)}
/* A row that has come back empty says so once, quietly, rather than being
   left blank — a gap in a column of facts reads as a rendering fault. */
.kv dd.none{color:var(--tx3);font-weight:400}
.sec-t:first-child{margin-top:0}
/* Headline block on a detail modal — the one number that matters. */
.hero{display:flex;align-items:center;gap:15px;padding:13px 16px;border-radius:var(--rl);
  margin-bottom:13px;border:1px solid var(--bd);background:var(--bgI)}
.hero.crit{background:var(--rdBg);border-color:var(--rd)}
.hero.warn{background:var(--amBg);border-color:var(--am)}
.hero.info{background:var(--blBg);border-color:var(--bl)}
.hero.ok{background:var(--gnBg);border-color:var(--gn)}
.hero-n{font-size:26px;font-weight:600;line-height:1;letter-spacing:var(--ls-n);
  font-variant-numeric:tabular-nums}
.hero-t{font-size:13px;font-weight:600}
.hero-s{font-size:12px;color:var(--tx2);margin-top:3px;font-weight:400}

/* == 16. Forms ============================================================= */
.fld{margin-bottom:14px}
.fld label,label.lbl{display:block;font-size:12.5px;font-weight:500;color:var(--tx2);
  letter-spacing:0;margin-bottom:6px}
.fld label .req,label.lbl .req{color:var(--rd);margin-left:2px}
.fld input,.fld select,.fld textarea,
input[type=text],input[type=email],input[type=date],input[type=time],input[type=number],
input[type=search],input[type=password],input[type=tel],input[type=url],select,textarea{
  width:100%;padding:0 11px;height:36px;border:1px solid var(--bdS);border-radius:var(--r);
  font-family:var(--f);font-size:13px;font-weight:400;background:var(--bg2);color:var(--tx);
  /* A control takes the browser's own `font`, which resets the figures to
     proportional: an amount typed into a column of line items did not
     line up with the one above it. */
  font-variant-numeric:tabular-nums;
  outline:none;transition:border-color .12s,background .12s,box-shadow .12s}
textarea{padding:10px 12px;height:auto;resize:vertical;min-height:88px;line-height:1.6}
.fld input:focus,.fld select:focus,.fld textarea:focus,
input:focus,select:focus,textarea:focus{border-color:var(--acD);box-shadow:var(--ring);
  background:var(--bg2)}
input:disabled,select:disabled,textarea:disabled{opacity:.55;cursor:not-allowed}
input[type=color]{width:100%;height:32px;padding:2px;cursor:pointer}
input[type=range]{width:100%;accent-color:var(--ac);padding:0;height:auto}
.fld-row2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px}
.fld-row3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.fld-row4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
@media(max-width:680px){.fld-row2,.fld-row3,.fld-row4{grid-template-columns:minmax(0,1fr)}}
.hint{font-size:12px;color:var(--tx3);margin-top:5px;font-weight:400;text-transform:none;
  letter-spacing:0;line-height:1.5}
.err-txt{font-size:12px;color:var(--rd);margin-top:5px;display:none;font-weight:500}
.fld.has-err input,.fld.has-err select,.fld.has-err textarea,.fld.has-err .ss-toggle{
  border-color:var(--rd)}
.fld.has-err .err-txt{display:block}
/* Input with a fixed prefix or suffix: rupee, per cent, .effred.com */
.ig{display:flex;align-items:stretch}
.ig .pfx,.ig .sfx{display:flex;align-items:center;padding:0 10px;background:var(--bgI);
  border:1px solid var(--bdS);font-size:12.5px;font-weight:500;color:var(--tx2);
  white-space:nowrap}
.ig .pfx{border-right:none;border-radius:var(--r) 0 0 var(--r)}
.ig .sfx{border-left:none;border-radius:0 var(--r) var(--r) 0}
.ig input{border-radius:0}
.ig > input:first-child{border-radius:var(--r) 0 0 var(--r)}
.ig > input:last-child{border-radius:0 var(--r) var(--r) 0}
.check{display:flex;align-items:flex-start;gap:10px;cursor:pointer;padding:11px 13px;
  border:1px solid var(--bd);border-radius:var(--rl);background:var(--bgI);
  transition:border-color .12s,background .12s}
.check:hover{border-color:var(--ac);background:var(--bg2)}
.check input{margin-top:1px;accent-color:var(--ac);width:14px;height:14px;flex-shrink:0}
.check-title{font-weight:500;font-size:13px;color:var(--tx);display:block}
.check-sub{font-size:12px;color:var(--tx3);margin-top:3px;display:block;font-weight:500;
  line-height:1.5}
/* Toggle switch for settings rows */
.sw-t{width:36px;height:20px;border-radius:10px;background:var(--bg3);
  border:1px solid var(--bd);position:relative;cursor:pointer;flex-shrink:0;
  transition:background .18s,border-color .18s}
.sw-t::after{content:'';position:absolute;top:1px;left:1px;width:16px;height:16px;
  border-radius:50%;background:var(--bg2);box-shadow:var(--sh);transition:left .18s}
.sw-t.on{background:var(--ac);border-color:var(--ac)}
.sw-t.on::after{left:17px}
.set-row{display:flex;align-items:center;gap:13px;padding:11px 0;
  border-bottom:1px solid var(--bdL)}
.set-row:last-child{border-bottom:none}
.set-b{flex:1;min-width:0}
.set-n{font-size:13px;font-weight:500}
.set-d{font-size:12px;color:var(--tx3);margin-top:3px;font-weight:400;line-height:1.5}
/* Section tabs inside a form dialog */
.ftabs{display:flex;gap:1px;background:var(--bg3);border-radius:7px;padding:2px;
  margin-bottom:13px;width:max-content;max-width:100%;overflow-x:auto}
.ftab{border:none;background:none;font-family:var(--f);font-size:12px;font-weight:500;
  color:var(--tx2);padding:6px 14px;border-radius:5px;cursor:pointer;white-space:nowrap}
.ftab.on{background:var(--bg2);color:var(--tx);box-shadow:var(--sh)}
.ftab.err{color:var(--rd)}
.ftab.err::after{content:'\00B7';margin-left:4px;font-size:15px;line-height:0}
.fpane{display:none}
.fpane.on{display:block;animation:fadeIn .16s ease-out}
/* Searchable select */
.ss{position:relative}
.ss-toggle{width:100%;padding:0 26px 0 11px;height:36px;background:var(--bg2);
  color:var(--tx);border:1px solid var(--bdS);border-radius:var(--r);font-size:13px;
  cursor:pointer;text-align:left;font-family:var(--f);position:relative;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;
  align-items:center;gap:7px}
.ss-toggle:after{content:"";position:absolute;right:10px;top:50%;width:5px;height:5px;
  border-right:1.5px solid var(--tx3);border-bottom:1.5px solid var(--tx3);
  transform:translateY(-70%) rotate(45deg)}
.ss-toggle.placeholder{color:var(--tx3)}
.ss-panel{position:fixed;z-index:1000;background:var(--bg2);border:1px solid var(--bd);
  border-radius:9px;box-shadow:var(--shL);display:none;flex-direction:column;
  overflow:hidden;min-width:220px;max-width:460px}
.ss.open .ss-panel{display:flex}
.ss.open .ss-toggle{border-color:var(--ac);box-shadow:var(--ring)}
.ss-search{flex:0 0 auto;padding:7px;border-bottom:1px solid var(--bd)}
.ss-search input{padding:0 9px;height:30px;font-size:11.5px}
.ss-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:4px}
.ss-opt{padding:7px 10px;border-radius:5px;cursor:pointer;font-size:12px;display:flex;
  align-items:center;gap:8px}
.ss-opt:hover,.ss-opt.hl{background:var(--bg3)}
.ss-opt.sel{color:var(--ac);font-weight:500}
.ss-empty{padding:13px;text-align:center;color:var(--tx3);font-size:10.5px}
.ss-foot{flex:0 0 auto;padding:6px 8px;border-top:1px solid var(--bd);display:flex;gap:6px}
.ss-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px}
.tag{background:var(--bg3);border:1px solid var(--bd);border-radius:var(--rp);
  padding:2px 8px;font-size:9.5px;font-weight:500;display:inline-flex;
  align-items:center;gap:5px}
.tag button{background:none;border:none;color:var(--tx3);cursor:pointer;font-size:12px;
  line-height:1;padding:0}
.tag button:hover{color:var(--rd)}
/* Upload */
.upload-zone{border:1.5px dashed var(--bd);border-radius:var(--rx);padding:22px;
  text-align:center;cursor:pointer;background:var(--bg)}
.upload-zone:hover,.upload-zone.drag{border-color:var(--ac);background:var(--acBg)}
.upload-zone p{font-size:11.5px;color:var(--tx2);font-weight:500;display:flex;
  align-items:center;justify-content:center;gap:8px}
.upload-zone .us{font-size:9.5px;color:var(--tx3);font-weight:500;margin-top:4px;
  display:block}
.file-row{display:flex;align-items:center;gap:9px;padding:8px 10px;
  border:1px solid var(--bd);border-radius:var(--r);background:var(--bg2);margin-top:6px}
.file-ic{width:28px;height:28px;border-radius:6px;display:grid;place-items:center;
  background:var(--bg3);color:var(--tx2);flex-shrink:0;font-size:8px;font-weight:600;
  font-family:var(--fm)}
/* Role / option picker cards */
.roles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px}
@media(max-width:700px){.roles{grid-template-columns:minmax(0,1fr)}}
.role-c{border:1px solid var(--bd);border-radius:var(--rl);padding:11px 13px;
  cursor:pointer;background:var(--bg2);text-align:left;font-family:var(--f);
  color:var(--tx);transition:border-color .14s,background .14s}
.role-c:hover{border-color:var(--ac)}
.role-c.on{border-color:var(--ac);background:var(--acBg)}
.role-c-t{font-size:11.5px;font-weight:600;display:flex;align-items:center;gap:7px}
.role-c-d{font-size:9.5px;color:var(--tx2);margin-top:5px;line-height:1.55;font-weight:500}

/* == 17. Stepper / wizard ================================================== */
.stp{display:flex;align-items:center;gap:0;margin-bottom:16px;overflow-x:auto;
  scrollbar-width:none;padding-bottom:2px}
.stp::-webkit-scrollbar{display:none}
.stp-i{display:flex;align-items:center;gap:8px;flex-shrink:0}
.stp-n{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;
  font-size:9.5px;font-weight:600;background:var(--bg3);color:var(--tx3);
  border:1px solid var(--bd);flex-shrink:0}
.stp-i.on .stp-n{background:var(--ac);color:var(--acTx,#fff);border-color:var(--ac)}
.stp-i.dn .stp-n{background:var(--gn);color:#fff;border-color:var(--gn)}
.stp-l{font-size:10.5px;font-weight:500;color:var(--tx3);white-space:nowrap}
.stp-i.on .stp-l{color:var(--tx)} .stp-i.dn .stp-l{color:var(--tx2)}
.stp-bar{width:34px;height:1.5px;background:var(--bd);margin:0 10px;flex-shrink:0}
.stp-i.dn + .stp-bar{background:var(--gn)}

/* == 18. Timeline / activity / approvals =================================== */
.tl{position:relative;padding-left:17px}
.tl::before{content:'';position:absolute;left:4px;top:5px;bottom:5px;width:1px;
  background:var(--bd)}
.tl-i{position:relative;padding:0 0 13px 0}
.tl-i:last-child{padding-bottom:0}
.tl-i::before{content:'';position:absolute;left:-16px;top:4px;width:8px;height:8px;
  border-radius:50%;background:var(--ac);border:2px solid var(--bg2)}
.tl-i.ok::before{background:var(--gn)} .tl-i.warn::before{background:var(--am)}
.tl-i.rd::before{background:var(--rd)} .tl-i.mut::before{background:var(--tx3)}
.tl-s{font-size:11.5px;font-weight:600;line-height:1.5}
.tl-s b{font-weight:600}
.tl-m{font-size:9px;color:var(--tx3);margin-top:2px;font-weight:600}
/* Approval chain — a compact horizontal read of who is next. */
.chain{display:flex;align-items:center;gap:0;flex-wrap:wrap}
.chain-s{display:flex;align-items:center;gap:7px;padding:5px 9px;
  border:1px solid var(--bd);border-radius:var(--rp);background:var(--bg2);
  font-size:10px;font-weight:500}
.chain-s.dn{border-color:var(--gn);color:var(--gn);background:var(--gnBg)}
.chain-s.now{border-color:var(--am);color:var(--am);background:var(--amBg)}
.chain-s.rj{border-color:var(--rd);color:var(--rd);background:var(--rdBg)}
.chain-a{width:16px;height:1.5px;background:var(--bd);flex-shrink:0}
/* Approval card — one component, used in the inbox, on records and in email. */
.apc{border:1px solid var(--bd);border-radius:var(--rl);background:var(--bg2);
  padding:11px 13px;margin-bottom:7px;display:flex;gap:12px;align-items:flex-start}
.apc:hover{border-color:var(--tx3)}
.apc-b{flex:1;min-width:0}
.apc-t{font-size:12px;font-weight:600;letter-spacing:0}
.apc-m{font-size:9.5px;color:var(--tx3);font-weight:600;margin-top:3px;display:flex;
  gap:9px;flex-wrap:wrap}
.apc-a{display:flex;gap:6px;flex-shrink:0;align-items:center}
.apc-amt{font-family:var(--f);font-variant-numeric:tabular-nums;font-size:14px;font-weight:600;white-space:nowrap}
/* SLA pip */
.sla{display:inline-flex;align-items:center;gap:4px;font-size:9px;font-weight:600}
.sla.ok{color:var(--gn)} .sla.warn{color:var(--am)} .sla.br{color:var(--rd)}

/* == 19. Board (kanban) ==================================================== */
.kb{display:flex;gap:9px;overflow-x:auto;padding-bottom:8px;align-items:flex-start}
.kb-c{width:274px;flex-shrink:0;background:var(--bgI);border:1px solid var(--bd);
  border-radius:var(--rl);display:flex;flex-direction:column;
  max-height:calc(100vh - 250px)}
.kb-h{padding:9px 11px;border-bottom:1px solid var(--bd);display:flex;
  align-items:center;gap:7px}
.kb-t{font-size:12px;font-weight:600;color:var(--tx2)}
.kb-n{font-size:9px;font-weight:600;background:var(--bg3);border-radius:var(--rp);
  padding:1px 6px;color:var(--tx2)}
.kb-sum{margin-left:auto;font-family:var(--f);font-variant-numeric:tabular-nums;font-size:10.5px;font-weight:500;
  color:var(--tx3)}
.kb-b{padding:7px;overflow-y:auto;flex:1;min-height:60px}
.kbc{background:var(--bg2);border:1px solid var(--bd);border-radius:9px;padding:9px 10px;
  margin-bottom:6px;cursor:pointer;box-shadow:var(--sh)}
.kbc:hover{border-color:var(--ac)}
.kbc-t{font-size:11.5px;font-weight:500;line-height:1.35;margin-bottom:6px}
.kbc-m{font-size:9px;color:var(--tx3);font-weight:600;display:flex;align-items:center;
  gap:8px;flex-wrap:wrap;margin-top:6px}

/* == 20. Calendar ========================================================== */
.cal{border:1px solid var(--bd);border-radius:var(--rl);overflow:hidden;
  background:var(--bg2)}
.cal-hd{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));background:var(--bg3)}
.cal-hd div{padding:6px 8px;font-size:10.5px;font-weight:500;color:var(--tx2);
  text-align:center;
  border-right:1px solid var(--bd)}
.cal-hd div:last-child{border-right:none}
.cal-gd{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.cal-d{min-height:82px;padding:5px 6px;border-right:1px solid var(--bdL);
  border-bottom:1px solid var(--bdL);position:relative}
.cal-d:nth-child(7n){border-right:none}
.cal-d.off{background:var(--bgI)}
.cal-d.today{background:var(--acBg)}
.cal-n{font-size:10px;font-weight:600;color:var(--tx2);margin-bottom:4px}
.cal-d.today .cal-n{color:var(--ac)}
.cal-e{font-size:9px;font-weight:500;padding:2px 5px;border-radius:4px;margin-bottom:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}

/* == 21. Feedback: banners, toasts, tooltips, empty ======================== */
.banner{max-width:1860px;margin:9px auto 0;padding:8px 13px;font-size:10.5px;
  font-weight:500;background:var(--amBg);color:var(--am);border:1px solid var(--am);
  border-radius:var(--r);display:flex;gap:8px;align-items:center}
.banner.info{background:var(--blBg);color:var(--bl);border-color:var(--bl)}
.banner.rd{background:var(--rdBg);color:var(--rd);border-color:var(--rd)}
.banner.gn{background:var(--gnBg);color:var(--gn);border-color:var(--gn)}
.banner .gap{flex:1}
/* Impersonation runs edge to edge above everything, and is impossible to miss. */
/* Pinned to one red in both themes. The dark palette's --rd is a light coral
   that white text cannot sit on, and this is the one bar that must never be
   hard to read. */
.imp{background:#a72d2d;color:#fff;font-size:10.5px;font-weight:600;padding:6px 14px;
  display:flex;align-items:center;gap:9px;position:sticky;top:0;z-index:130}
.imp .btn{background:#fff;border-color:#fff;color:#a72d2d}
.imp .btn:hover{background:#f2e6e6;border-color:#f2e6e6;color:#8f2626}
.toast-w{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:1200;
  display:flex;flex-direction:column;gap:7px;align-items:center;max-width:92%}
.toast{background:var(--bg2);border:1px solid var(--bd);border-radius:9px;
  padding:10px 18px;font-size:11.5px;font-weight:600;box-shadow:var(--shM);
  animation:tin .18s ease-out;display:flex;align-items:flex-start;gap:10px;min-width:250px}
.toast.ok{border-color:var(--gn)} .toast.err{border-color:var(--rd)}
.toast.warn{border-color:var(--am)}
.toast-ic{flex-shrink:0;margin-top:1px;color:var(--ac)}
.toast.ok .toast-ic{color:var(--gn)} .toast.err .toast-ic{color:var(--rd)}
.toast.warn .toast-ic{color:var(--am)}
.toast-title{font-weight:600;font-size:11.5px}
.toast-msg{color:var(--tx2);font-size:10.5px;font-weight:500;margin-top:2px;line-height:1.5}
@keyframes tin{from{opacity:0;transform:translateY(10px)}}
.tip{position:fixed;z-index:1400;max-width:270px;padding:7px 10px;background:#16181d;
  color:#f2f3f5;border-radius:7px;font-size:11px;line-height:1.45;font-weight:500;
  pointer-events:none;opacity:0;transform:translateY(-3px);
  transition:opacity .13s,transform .13s;box-shadow:0 8px 22px -8px rgba(0,0,0,.5)}
.tip.show{opacity:1;transform:none}
.empty{font-size:11px;color:var(--tx3);text-align:center;padding:34px 20px}
/* Inside a dashboard card, one quiet line. The full poster — icon tile,
   heading, sentence — is for a whole screen with nothing on it; in a card it
   is 120 px of nothing next to a card that is full, which is what makes a
   quiet week look like a broken product. */
.cd-bd > .empty{padding:14px 0;text-align:left;display:flex;align-items:center;
  gap:9px;min-height:0}
.cd-bd > .empty .empty-ic{width:26px;height:26px;border-radius:8px;flex:none;
  margin:0}
.cd-bd > .empty .empty-ic svg.i{width:14px;height:14px}
.cd-bd > .empty .big{margin:0;font-size:11.5px}
.cd-bd > .empty .btn{margin:0 0 0 auto}
.empty .big{font-size:12.5px;font-weight:600;color:var(--tx2);margin-bottom:5px}
.empty .btn{margin-top:11px}
.empty-ic{width:44px;height:44px;border-radius:13px;background:var(--bg3);color:var(--tx3);
  display:grid;place-items:center;margin:0 auto 11px}
/* Skeletons */
@keyframes shimmer{0%{background-position:-560px 0}100%{background-position:560px 0}}
.sk{background:linear-gradient(90deg,var(--bg3) 25%,var(--bgH) 50%,var(--bg3) 75%);
  background-size:560px 100%;animation:shimmer 1.25s infinite linear;border-radius:5px;
  height:11px}
.sk-kpi{height:66px;border-radius:var(--rl);border:1px solid var(--bd)}
.sk-card{height:250px;border-radius:var(--rx);border:1px solid var(--bd)}
.sk-pc{height:146px;border-radius:var(--rx);border:1px solid var(--bd)}
.sk-row{height:29px;border-radius:5px;margin-bottom:5px}
@keyframes fadeIn{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}
.fade-in{animation:fadeIn .2s ease-out}

/* == 22. Bars and donut (chart fallback) =================================== */
.bars{display:flex;flex-direction:column;gap:7px}
.bar-row{display:grid;grid-template-columns:minmax(80px,160px) minmax(0,1fr) 56px;gap:10px;
  align-items:center;font-size:10.5px}
.bar-row.drill{cursor:pointer}
.bar-row.drill:hover .bar-fill{opacity:.8}
.bar-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.bar-track{height:8px;background:var(--bg3);border-radius:4px;overflow:hidden}
.bar-fill{display:block;height:100%;background:var(--ac);border-radius:4px;transition:width .35s}
.bar-val{text-align:right;font-family:var(--f);font-variant-numeric:tabular-nums;font-weight:500;font-size:10.5px}
.donut{width:126px;height:126px;border-radius:50%;flex-shrink:0;position:relative;
  display:grid;place-items:center}
.donut::after{content:'';position:absolute;inset:17px;border-radius:50%;
  background:var(--bg2)}
.donut-c{position:relative;z-index:1;text-align:center}
.donut-v{font-size:19px;font-weight:600;letter-spacing:-.015em;line-height:1;
  font-variant-numeric:tabular-nums}
.donut-l{font-size:10px;font-weight:500;color:var(--tx3);margin-top:3px}
.lgd{display:flex;flex-direction:column;gap:6px}
.lgd-i{display:flex;align-items:center;gap:8px;font-size:10.5px;font-weight:600}
.lgd-i .sw2{width:9px;height:9px;border-radius:3px;flex-shrink:0}
.lgd-i .vl{margin-left:auto;font-family:var(--f);font-variant-numeric:tabular-nums;font-weight:500}

/* == 23. Auth / public shell =============================================== */
.auth{min-height:100vh;display:grid;place-items:center;padding:22px;background:var(--bg)}
.auth-c{width:100%;max-width:408px}
.auth-card{background:var(--bg2);border:1px solid var(--bd);border-radius:18px;
  padding:30px 30px 26px;box-shadow:var(--shM)}
.auth h1{font-size:23px;font-weight:600;letter-spacing:var(--ls-h);margin-bottom:6px}
.auth-s{font-size:11.5px;color:var(--tx2);margin-bottom:20px;line-height:1.55;
  font-weight:500}
.auth-ft{text-align:center;font-size:12px;color:var(--tx3);margin-top:16px;font-weight:400}
.otp{display:flex;gap:8px;justify-content:center}
.otp input{width:42px;height:50px;text-align:center;font-size:19px;font-weight:600;
  font-family:var(--fm);padding:0}
/* Password strength meter */
.pw{display:flex;gap:4px;margin-top:7px}
.pw i{flex:1;height:3px;border-radius:2px;background:var(--bg3)}
.pw.s1 i:nth-child(1){background:var(--rd)}
.pw.s2 i:nth-child(-n+2){background:var(--am)}
.pw.s3 i:nth-child(-n+3){background:var(--bl)}
.pw.s4 i{background:var(--gn)}

/* -- 23b. The sign-in shell ------------------------------------------------
   Every door somebody signs in through is one shell: the company portal,
   the control plane, the monitoring plane, and the five pages either side
   of a password - forgot, reset, the code, the first sign-in and the second
   factor. The band on the left is whose door this is; the right is the way
   in. Thousands of people read it every morning, so it says the name, one
   line about what the portal is, and how the door is defended - the same
   facts the code makes true, and nothing it does not.

   The band is the company's own colour taken DEEP: --acD, which
   brand_palette already guarantees clears 4.5:1 under white writing, mixed
   further toward black - which only widens that - so a pale yellow brand
   gets a dark olive band that white text reads on, rather than a yellow one
   it cannot. The control and monitoring planes wear Effred's own navy
   instead (.is-ef). The pattern is a dot grid in 9% white fading off the
   top-left corner, and a hairline isometric lattice in 6% white out of the
   bottom-right: drawn once, static, because nothing on a page somebody is
   typing a password into may move.

   Below 1024px the band collapses to a header strip above the form - on a
   tablet or a phone the whole answer is whose portal this is - and the
   defence moves under the card as one quiet line (.auth-foot). No 100vh
   below 700px: body{zoom} there puts a viewport unit out by the zoom. */
.auth-pg{background:var(--bg)}
.auth-sh{--auth-g1:color-mix(in srgb,var(--acD) 72%,#04070b);
  --auth-g2:color-mix(in srgb,var(--acD) 46%,#04070b);
  min-height:100vh;display:grid;background:var(--bg);
  grid-template-columns:minmax(0,55fr) minmax(0,45fr)}
.auth-sh.is-ef{--auth-g1:#15233f;--auth-g2:#070d1a}
.auth-br{position:relative;isolation:isolate;overflow:hidden;color:#fff;
  background:var(--auth-g1);padding:44px clamp(36px,5vw,76px) 34px;display:flex;
  flex-direction:column;min-height:100vh;min-width:0}
/* Whose door. A logo drawn for white paper is unreadable on a dark band and
   this is the one place nobody can check what a customer uploaded, so it
   sits on its own white chip; no logo is the initial on a glass tile. */
.auth-org{display:flex;align-items:center;gap:13px;min-width:0}
.auth-logo{display:grid;place-items:center;height:46px;padding:0 13px;
  border-radius:var(--rl);background:#fff;flex:none;max-width:210px;
  box-shadow:0 1px 2px rgba(0,0,0,.2)}
/* A height, not a max-height: an SVG logo with a viewBox and no width has
   no intrinsic size, and `auto` on both axes collapses it to nothing. */
.auth-logo img{display:block;height:30px;width:auto;max-width:184px;
  object-fit:contain}
.auth-ini{width:46px;height:46px;border-radius:var(--rl);display:grid;
  place-items:center;flex:none;background:rgba(255,255,255,.1);
  border:1px solid rgba(255,255,255,.24);color:#fff;font-size:19px;
  font-weight:600}
.auth-ini svg.i{width:22px;height:22px}
/* Effred One, from its own file: the tile and the white wordmark. */
.auth-one{display:block;height:34px;width:auto;flex:none}
.auth-plane{font-size:13px;font-weight:500;color:rgba(255,255,255,.72);
  padding-left:14px;border-left:1px solid rgba(255,255,255,.2);line-height:1.3}
.auth-org-t{display:flex;flex-direction:column;gap:4px;min-width:0}
.auth-org-n{font-size:15px;font-weight:600;letter-spacing:var(--ls-t);
  line-height:1.2;overflow-wrap:anywhere}
.auth-org-k{font-size:12.5px;font-weight:400;color:rgba(255,255,255,.72)}
.auth-hero{margin:auto 0;padding:52px 0 44px;max-width:520px}
.auth-hl{font-size:clamp(28px,2.5vw,38px);line-height:1.14;font-weight:600;
  text-wrap:balance;
  letter-spacing:var(--ls-d);margin:0 0 12px;color:#fff;overflow-wrap:anywhere}
.auth-lede{font-size:15px;line-height:1.6;color:rgba(255,255,255,.78);
  margin:0;max-width:30em}
/* The defence, in one line at the foot of the band. Each clause is a thing
   the code does - see _auth_brand.html. */
.auth-br-ft{margin:0;font-size:12.5px;line-height:1.6;
  color:rgba(255,255,255,.66)}
/* The way in. */
.auth-main{display:flex;flex-direction:column;min-width:0;min-height:100vh;
  padding:40px clamp(22px,4vw,64px) 26px}
.auth-pane{width:100%;max-width:408px;margin:auto}
.auth-sh .auth-card{border-radius:var(--rx);padding:32px 30px 28px;
  box-shadow:var(--sh)}
.auth-t{font-size:24px;font-weight:600;letter-spacing:var(--ls-h);line-height:1.2;
  margin:0 0 7px;color:var(--tx);overflow-wrap:anywhere}
.auth-sh .auth-s{font-size:13px;font-weight:400;line-height:1.55;
  color:var(--tx2);margin-bottom:24px}
.auth-sh .fld{margin-bottom:16px}
.auth-sh .fld label{font-size:12px;font-weight:500;letter-spacing:0;
  text-transform:none;color:var(--tx2);margin-bottom:7px}
.auth-sh .fld input{height:42px;font-size:14px;border-radius:var(--r);
  background:var(--bg2)}
.auth-sh .fld input:focus,.auth-sh .otp input:focus{border-color:var(--acD);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--acD) 20%,transparent)}
.auth-sh .err-txt{font-size:12px;line-height:1.5;margin-top:7px}
.auth-sh .hint{font-size:12px}
.auth-sh .btn-lg{height:42px;font-size:14px;font-weight:500;border-radius:var(--r)}
.auth-sh .btn:focus-visible,.auth-txtbtn:focus-visible,.auth-link:focus-visible,
.auth-eye:focus-visible{outline:2px solid var(--acD);outline-offset:2px}
/* Links are --acD, the shade guaranteed dark enough to be writing; the raw
   brand colour is a button ground and nothing else. */
/* The sign-in form. "Forgot password" is drawn in the password's label row
   and written LAST in the source, after Sign in, so one Tab from the email
   box reaches the password. The form is one grid column; the link shares
   the password field's cell at its top right, on the label's baseline.
   Overlap needs a definite row AND column on both, which is why each
   placed child names both - an auto column would open a second track. */
.auth-f{display:grid;grid-template-columns:minmax(0,1fr)}
.auth-f>.auth-f-pw,.auth-f>.auth-fgt{grid-row:2;grid-column:1;align-self:baseline}
.auth-f>.auth-go{grid-row:3;grid-column:1}
.auth-f>.auth-fgt{justify-self:end;position:relative;z-index:1}
.auth-link{font-size:12.5px;font-weight:500;color:var(--acD);
  text-decoration:none;border-radius:3px}
.auth-link:hover{text-decoration:underline;text-underline-offset:2px}
.auth-txtbtn{background:none;border:none;padding:0;font:inherit;
  font-weight:500;color:var(--acD);cursor:pointer;text-decoration:underline;
  text-underline-offset:2px;border-radius:3px}
.auth-pw{position:relative}
.auth-sh .auth-pw input{padding-right:48px}
.auth-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:34px;height:34px;padding:0;border:none;background:none;
  border-radius:var(--r);cursor:pointer;color:var(--tx3);display:grid;
  place-items:center}
.auth-eye:hover{background:var(--bg3);color:var(--tx)}
.auth-eye svg.i{width:17px;height:17px}
.auth-caps{display:flex;align-items:center;gap:6px;margin-top:7px;
  font-size:12px;font-weight:500;color:var(--am)}
.auth-caps svg.i{width:14px;height:14px;flex:none}
/* Busy says so in words, and cannot be pressed twice. */
.auth-go{gap:9px}
.auth-go.is-busy{pointer-events:none}
.auth-spin{display:none;width:14px;height:14px;border-radius:50%;flex:none;
  border:2px solid currentColor;border-right-color:transparent;
  animation:spin .75s linear infinite}
.auth-go.is-busy .auth-spin{display:inline-block}
@media(prefers-reduced-motion:reduce){.auth-spin{animation:none;
  border-right-color:currentColor;opacity:.5}}
.auth-alert{display:flex;gap:10px;align-items:flex-start;margin:0 0 20px;
  padding:11px 13px;border-radius:var(--rl);background:var(--rdBg);color:var(--rd);
  font-size:12.5px;line-height:1.5;font-weight:500}
.auth-alert svg.i{width:16px;height:16px;flex:none;margin-top:1px}
.auth-or{display:flex;align-items:center;gap:12px;margin:20px 0;
  font-size:11.5px;font-weight:500;color:var(--tx3)}
.auth-or::before,.auth-or::after{content:'';flex:1;height:1px;
  background:var(--bd)}
.auth-help{margin:18px 0 0;font-size:12.5px;line-height:1.6;
  color:var(--tx3);text-align:center}
.auth-help + .auth-help{margin-top:8px}
.auth-help a,.auth-sh .auth-card a:not(.btn){color:var(--acD);font-weight:500}
.auth-em{font-weight:500;color:var(--tx);overflow-wrap:anywhere}
.auth-sep{height:1px;background:var(--bdL);margin:22px 0 18px}
.auth-ic{width:40px;height:40px;border-radius:var(--rl);display:grid;
  place-items:center;margin:0 0 16px;background:var(--acBg);color:var(--acD)}
.auth-ic.am{background:var(--amBg);color:var(--am)}
.auth-ic svg.i{width:19px;height:19px}
.auth-sh .otp{gap:9px}
.auth-sh .otp input{width:48px;height:56px;font-size:21px;border-radius:var(--rl);
  background:var(--bg2)}
.auth-foot{display:none;margin-top:26px;justify-content:center;
  flex-wrap:wrap;gap:6px 16px;font-size:11.5px;line-height:1.5;
  color:var(--tx3);text-align:center}
.auth-foot span{display:inline-flex;align-items:center;gap:6px}
.auth-vh{position:absolute!important;width:1px;height:1px;padding:0;
  margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
@media(max-width:1180px) and (min-width:1024px){
  .auth-br{padding-left:40px;padding-right:40px}
}
@media(max-width:1023px){
  .auth-sh{grid-template-columns:minmax(0,1fr);grid-template-rows:auto 1fr}
  .auth-br{min-height:0;padding:18px 24px;flex-direction:row;
    align-items:center}
  .auth-hero,.auth-br-ft{display:none}
  .auth-one{height:28px}
  .auth-logo{height:40px;padding:0 11px}
  .auth-logo img{height:26px;max-width:160px}
  .auth-ini{width:40px;height:40px;border-radius:var(--rl);font-size:17px}
  .auth-main{min-height:0;padding:36px 22px 26px}
  .auth-pane{margin:0 auto}
  .auth-foot{display:flex}
}
@media(max-width:700px){
  .auth-sh{min-height:0}
  .auth-br{padding:15px 18px}
  .auth-main{padding:22px 16px 22px}
  .auth-sh .auth-card{padding:24px 20px 22px;border-radius:var(--rx)}
  .auth-t{font-size:21px}
  .auth-sh .auth-s{margin-bottom:20px}
  .auth-sh .otp{gap:7px}
  .auth-sh .otp input{width:44px;height:52px}
}
/* Printed, a door is its card. The recovery codes on the second-factor
   screen are the one thing anybody prints from here, and a page of dark
   band is ink spent on nothing. */
@media print{
  .auth-sh{display:block;min-height:0}
  .auth-br,.auth-foot,.auth-help{display:none}
  .auth-main{min-height:0;padding:0}
  .auth-pane{max-width:none}
  .auth-sh .auth-card{box-shadow:none}
}

/* == 24. Footer ============================================================ */
.ft{text-align:center;padding:20px 0 8px;font-size:11.5px;color:var(--tx3);
  font-weight:500}
.ft .dot{opacity:.4;margin:0 6px}
/* The maker's mark. Smaller than the company's own name and on its own line,
   because it is a credit and not a co-signature. */
.ft-by{display:block;font-size:11px;font-weight:400;color:var(--tx3);
  margin-top:3px;letter-spacing:0}

/* == 25. Utilities ========================================================= */
.muted{color:var(--tx3)} .small{font-size:11.5px} .right{text-align:right}
.center{text-align:center} .nowrap{white-space:nowrap} .hidden{display:none!important}
.mono{font-family:var(--fm)} .bold{font-weight:600}
.flex{display:flex;align-items:center;gap:7px}
.wrap{flex-wrap:wrap} .col{flex-direction:column;align-items:stretch}
.between{justify-content:space-between} .grow{flex:1;min-width:0}
.mt0{margin-top:0} .mt8{margin-top:8px} .mt12{margin-top:12px} .mt16{margin-top:16px}
.mb0{margin-bottom:0} .mb8{margin-bottom:8px} .mb12{margin-bottom:12px}
.sep-h{height:1px;background:var(--bd);margin:13px 0}
.pre{font-family:var(--fm);font-size:10.5px;background:var(--bg);border:1px solid var(--bd);
  border-radius:8px;padding:11px;white-space:pre-wrap;margin-top:10px;max-height:270px;
  overflow:auto;line-height:1.6}
.gn-t{color:var(--gn)} .rd-t{color:var(--rd)} .am-t{color:var(--am)} .ac-t{color:var(--ac)}
.cur{font-weight:500;font-variant-numeric:tabular-nums}
.micro{font-size:10.5px;color:var(--tx3);font-weight:500;letter-spacing:0}

/* == 26. Responsive + print ================================================ */
@media(max-width:1023px){
  /* The rail is an off-canvas drawer behind a burger from here down — the
     treatment the phone proved out, minus the phone's zoom. The strip of
     chips it replaces ate three rows at the top of every tablet, clipped
     its own heading, and was the one band of the product that looked like
     neither the desk nor the app. */
  .nav-burger{display:grid}
  .side,.side.mini{position:fixed;top:0;bottom:0;left:0;
    width:min(300px,84vw);z-index:460;display:block;height:auto;
    max-height:none;padding:16px 12px 22px;overflow-y:auto;margin:0;
    background:var(--bg2);border-right:1px solid var(--bd);border-bottom:0;
    transform:translateX(-106%);transition:transform .18s ease}
  html.railopen .side{transform:none;
    box-shadow:0 14px 44px rgba(22,38,31,.3)}
  html.railopen .rail-bk{display:block}
  .side .side-t:not(:first-child){display:block}
  .side .sd{width:100%;border:0;background:none;padding:9px 11px;margin:0}
  .side .sd.on{background:var(--acBg)}
  .side .side-min{display:none}
  /* The rail is out of the flow here, so the shell gives the viewport back
     and the window is the scroller again. Two reasons, both load-bearing.

     A drawer is not a column: pinning the shell to the viewport would buy
     nothing and would put a second scrollbar inside a page that already has
     one, which is the whole fault this change exists to remove.

     And `100vh` is not to be trusted at these widths. `body{zoom:.8}` below
     700px scales the layout after it is computed, so a viewport unit under it
     is out by the zoom factor — a `100vh` box renders a quarter taller than
     the glass. Releasing the height here means a phone never evaluates it. */
  .shell{height:auto;display:block}
  .scr{height:auto;overflow:visible;min-width:0}
  .scr > .main{padding-left:18px}
  /* Full-width main with its own gutter — the rail is out of the flow. */
  .side + .main,.main{padding-left:18px;width:100%;margin-left:0;
    margin-right:0;min-width:0;max-width:100%}
  /* The wrapper, not just the label inside it. */
  .srch,.nav-search{display:none}
  .nav-tenant .tn-host{display:none}
}
@media(max-width:860px){
  .nav-tag,.nav-plane,.sw-btn .lb{display:none}
  .nav-one{height:22px}
  .nav-plane + .sep{display:none}
  /* The Admin button keeps its icon and loses its word, and the help icon
     goes — it is reachable from inside the page. Both used to wait until
     560 px, which is a hundred pixels below where the strip actually runs
     out of room. */
  #efHelp{display:none}
  .nav-in > .btn{padding:0 9px;font-size:0;gap:0}
  .nav-in > .btn svg.i{width:15px;height:15px}
  .ph h1{font-size:19px}
  .hail-h{font-size:20px}
  .rtw{max-height:none}
  .kg,.kg.k6,.kg.k5,.kg.k4,.kg.k3{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
}
@media(max-width:700px){
  /* The top strip carries a brand, a switcher, a search box, three icon
     actions, an Admin button and a profile ring. At this width that is more
     than fits, and what it did was push the profile ring off the right-hand
     edge — the one control that gets somebody signed out.

     So the strip drops to what cannot be reached any other way. The Admin
     button keeps its icon and loses its word; the tenant chip and the help
     icon go, because both are reachable from inside the page. */
  .nav-in{padding:0 8px;gap:5px}
  /* The brand is the one thing here that can give ground: it has a mark
     beside it and the company name is on every page anyway. Everything else
     in the strip is a control, and a control pushed off the right-hand edge
     is a control nobody can reach. */
  .nav-brand{font-size:13.5px;min-width:0;overflow:hidden;
    text-overflow:ellipsis;flex-shrink:1}
  .nav-brand .nav-mark{width:28px;height:28px;border-radius:9px;font-size:12px}
  .lk-n{font-size:13px}
  .nav-ico{width:30px}
  #efHelp{display:none}
  .nav-tenant{display:none}
  .nav-in > .btn{padding:0 8px;font-size:0;gap:0}
  .nav-in > .btn svg.i{width:15px;height:15px}
  .ph-act{width:100%}
  .ph-act .btn{flex:1;justify-content:center}
  /* Two tiles a row, not one. A single column of full-width stat cards is
     a screen of scrolling for five numbers; at the phone's 85% render two
     sit comfortably and the page halves in height. */
  .kg,.kg.k6,.kg.k5,.kg.k4,.kg.k3{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:8px}
  .sm-i{min-width:46%}
  .md-b,.md-h,.md-f{padding-left:14px;padding-right:14px}
}
@media(prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .av-ring.spin{animation:none}
}
@media print{
  .nav,.imp,.side,.btn,.tabs,.toolbar,.pgw,.ft,.dm,.chip-row,.nav-ico,.pf,#loadbar{
    display:none!important}
  /* A printer has no viewport and no scrollbar. Left pinned, the shell would
     print exactly one screen of a payroll run and drop the rest in silence. */
  .shell{height:auto;display:block}
  .scr{height:auto;overflow:visible}
  body:has(> .imp){display:block;height:auto}
  body{background:#fff}
  .cd,.ki,.pc{box-shadow:none;break-inside:avoid}
}

/* == 22. Search, the bell, the org chart and the week grid =================
   Everything here belongs to a control that existed in the nav and did
   nothing: the search box, the bell, and the two shapes the self-service
   screens needed that the kit did not carry — a reporting tree and a week
   of hours. */

/* -- The search results popover ------------------------------------------ */
.srch{position:relative;flex:1;max-width:340px;min-width:120px}
.srch .nav-search{width:100%}
.srch-pop{position:absolute;top:34px;left:0;right:0;z-index:320;
  max-height:min(72vh,520px);overflow:auto;background:var(--bg2);
  border:1px solid var(--bd);border-radius:var(--rx);box-shadow:var(--shL);
  padding:5px;display:none;animation:pop .14s ease-out}
.srch.open .srch-pop{display:block}
/* A group heading is a row now, because it carries two things beside the
   name: how many matched against how many are shown, and a way into the
   list that holds the rest. A count with no door is only a slightly better
   dead end. */
.srch-g{display:flex;align-items:baseline;gap:8px;
  font-size:11px;font-weight:500;color:var(--tx3);padding:8px 9px 4px}
.srch-g .gap{flex:1}
/* A figure, not a label: tabular, so "25 of 118" does not jitter. */
.srch-n{font-size:10.5px;font-weight:500;color:var(--tx3);letter-spacing:0;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.srch-more{font-size:9px;font-weight:600;color:var(--acD);letter-spacing:0;
  text-transform:none;white-space:nowrap;text-decoration:none}
.srch-more:hover{text-decoration:underline}
.srch-r{display:flex;align-items:center;gap:9px;padding:6px 9px;border-radius:7px;
  color:var(--tx);cursor:pointer;text-decoration:none}
.srch-r:hover,.srch-r.on{background:var(--bg3);text-decoration:none}
.srch-r.on{outline:1px solid var(--ac);outline-offset:-1px}
.srch-r .ic{width:22px;height:22px;border-radius:6px;background:var(--bg3);
  color:var(--tx2);display:grid;place-items:center;flex-shrink:0}
.srch-r .ic svg.i{width:13px;height:13px}
.srch-r .tx{min-width:0;flex:1}
/* Two spans in a flex row render on one line without this. Fixed five times. */
.srch-r .t{display:block;font-size:11.5px;font-weight:500;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.srch-r .s{display:block;font-size:9px;color:var(--tx3);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srch-note{padding:16px 12px;text-align:center;font-size:11px;color:var(--tx3);
  font-weight:500}
.srch-all{display:flex;align-items:center;gap:7px;margin-top:4px;padding:8px 9px;
  border-top:1px solid var(--bdL);font-size:10.5px;font-weight:600;
  color:var(--ac);cursor:pointer}
.srch-all:hover{text-decoration:none;background:var(--bg3);border-radius:0 0 9px 9px}
.srch-all svg.i{width:13px;height:13px}

/* -- The bell ------------------------------------------------------------- */
.bell{position:relative;flex-shrink:0}
.bell-pop{position:absolute;top:34px;right:0;z-index:320;width:308px;
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rx);
  box-shadow:var(--shL);display:none;overflow:hidden;animation:pop .14s ease-out}
.bell.open .bell-pop{display:block}
.bell-h{padding:9px 12px;border-bottom:1px solid var(--bdL);background:var(--bgI);
  font-size:11.5px;font-weight:600;display:flex;align-items:center;
  justify-content:space-between;gap:8px}
.bell-l{max-height:340px;overflow:auto;padding:4px}
.bell-i{display:block;padding:8px 9px;border-radius:7px;color:var(--tx);
  cursor:pointer;position:relative}
.bell-i:hover{background:var(--bg3);text-decoration:none}
.bell-i.new{background:var(--acBg)}
.bell-i.new:hover{background:var(--acBg);filter:brightness(.98)}
.bell-i .t{display:block;font-size:11.5px;font-weight:500;line-height:1.35}
.bell-i .s{display:block;font-size:9.5px;color:var(--tx3);font-weight:500;
  margin-top:2px;line-height:1.4}
.bell-i .w{display:block;font-size:8.5px;color:var(--tx3);font-weight:600;
  margin-top:3px;letter-spacing:.2px}
.bell-f{display:block;padding:8px;text-align:center;border-top:1px solid var(--bdL);
  font-size:10.5px;font-weight:600;color:var(--ac);cursor:pointer}
.bell-f:hover{background:var(--bg3);text-decoration:none}

/* -- The org chart --------------------------------------------------------
   Top down: one box at the root, a drop, a bar across the children, a drop
   into each. Built out of nested lists and four ::before/::after rules rather
   than an SVG, so it reads in reporting order to a screen reader, prints, and
   keeps every node a real link.

   The trick is that each child <li> draws half the horizontal bar on its own
   side. First child draws the right half, last child the left half, and the
   ones between draw both — which is what makes the bar stop at the outermost
   children instead of running past them. */
.og{overflow:auto;padding:8px 2px 20px}
.og-in{display:inline-block;min-width:100%}
.og ul{list-style:none;margin:0;padding:0;display:flex;justify-content:center}
.og-root{padding-top:0}
.og li{position:relative;padding:26px 12px 0;text-align:center;
  display:flex;flex-direction:column;align-items:center}
.og-root > li{padding-top:0}

/* The drop into this box from the bar above it. */
.og li::before{content:'';position:absolute;top:0;left:50%;width:1px;height:26px;
  background:var(--bd)}
.og-root > li::before{display:none}
/* Half a bar on each side, so the run stops at the outermost child. */
.og li::after{content:'';position:absolute;top:0;height:1px;background:var(--bd);
  left:0;right:0}
.og li:first-child::after{left:50%}
.og li:last-child::after{right:50%}
.og li:only-child::after{display:none}
/* The drop out of a box towards its children. */
.og li > ul{position:relative;padding-top:26px}
.og li > ul::before{content:'';position:absolute;top:0;left:50%;width:1px;
  height:26px;background:var(--bd)}

.og-c{display:inline-block}
.og-b{display:flex;flex-direction:column;align-items:center;gap:3px;
  width:192px;padding:14px 12px 12px;border:1px solid var(--bd);
  border-radius:var(--rx);background:var(--bg2);color:var(--tx);
  box-shadow:var(--sh);transition:border-color .15s,box-shadow .15s,
  transform .15s}
a.og-b:hover{border-color:var(--ac);box-shadow:var(--shM);
  transform:translateY(-1px);text-decoration:none}
.og-c.top .og-b{border-color:var(--ac);background:var(--acBg)}
.og-c.me .og-b{border-color:var(--ac);box-shadow:var(--ring)}
.og-b .av{margin-bottom:5px}
.og-n{display:block;font-size:12.5px;font-weight:600;letter-spacing:0;
  line-height:1.3;max-width:100%;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* The title may take two lines before it clips: "Senior Operations
   Coordinator" cut to "Senior Operations C…" was most of what "the cards do
   not read well" meant on a real company's chart. */
.og-t{display:block;font-size:10.5px;color:var(--tx2);font-weight:500;
  line-height:1.35;max-width:100%;overflow:hidden;display:-webkit-box;
  -webkit-line-clamp:2;-webkit-box-orient:vertical}
.og-d{display:block;font-size:10px;color:var(--tx3);font-weight:500;
  margin-top:2px;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.og-k{display:inline-block;margin-top:5px;padding:1px 7px;border-radius:var(--rp);
  background:var(--bg3);color:var(--tx2);font-size:8.5px;font-weight:600}
/* The fold control under a card with a team below it. A shut branch is
   tinted, so a chart folded to its top row says where the rest went. */
.og-fold{margin-top:5px;padding:2px 9px;border-radius:var(--rp);
  border:1px solid var(--bd);background:var(--bg2);color:var(--tx3);
  font-size:9px;font-weight:600;cursor:pointer;font-family:var(--f);
  line-height:1.6;transition:border-color .14s,color .14s}
.og-fold:hover{border-color:var(--ac);color:var(--ac)}
.og-fold.shut{background:var(--acBg);color:var(--ac);
  border-color:color-mix(in srgb,var(--ac) 30%,var(--bd))}

/* On a narrow screen a wide tree is unusable side to side, so it becomes the
   indented list it used to be — same markup, different rules. */
@media (max-width:820px){
  .og ul{display:block}
  .og li{padding:0 0 0 22px;text-align:left;align-items:flex-start}
  .og li::before{top:0;bottom:0;left:8px;height:auto}
  .og li:last-child::before{bottom:auto;height:19px}
  .og li::after{top:19px;left:8px;right:auto;width:11px}
  .og li:first-child::after{left:8px}
  .og-root > li{padding-left:0}
  .og-root > li::after{display:none}
  .og li > ul{padding-top:2px}
  .og li > ul::before{display:none}
  .og-b{flex-direction:row;align-items:center;width:auto;min-width:0;
    max-width:340px;text-align:left;padding:7px 11px 7px 8px;margin:3px 0}
  .og-b .av{margin:0}
  .og-b > span:not(.av){align-items:flex-start}
  .og-n,.og-t,.og-d{text-align:left}
  .og-k{margin-top:0}
}

/* -- One person's chain, top of the company down to them ------------------ */
.ogc{list-style:none;margin:0;padding:0}
.ogc li{position:relative;padding:0 0 0 20px}
.ogc li::before{content:'';position:absolute;left:6px;top:0;bottom:0;
  border-left:1px solid var(--bd)}
.ogc li:first-child::before{top:16px}
.ogc li:last-child::before{bottom:auto;height:16px}
.ogc li::after{content:'';position:absolute;left:6px;top:16px;width:10px;
  border-top:1px solid var(--bd)}
.ogc li:first-child::after{display:none}
.ogc-b{display:flex;align-items:center;gap:9px;padding:5px 8px;border-radius:8px;
  color:var(--tx)}
.ogc-b:hover{background:var(--bg3);text-decoration:none}
.ogc li.me .ogc-b{background:var(--acBg)}
.ogc-x{min-width:0;flex:1}
.ogc-n{display:block;font-size:11.5px;font-weight:500;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ogc-t{display:block;font-size:9.5px;color:var(--tx3);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* -- The week of hours ----------------------------------------------------
   Seven columns on a desktop, stacked on a phone. The day header carries its
   own state — a week off, a holiday, an approved day away — because that is
   what decides whether an empty cell is a problem. */
.tsg{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px}
.tsd{border:1px solid var(--bd);border-radius:var(--rl);background:var(--bg2);
  min-height:148px;display:flex;flex-direction:column;overflow:hidden;
  transition:border-color .13s,box-shadow .13s}
.tsd:not(.off):hover{border-color:var(--ac);box-shadow:var(--sh)}
.tsd.off{background:var(--bgI);border-style:dashed}
.tsd.today{border-color:var(--ac);box-shadow:var(--ring)}
.tsd-h{padding:6px 8px;border-bottom:1px solid var(--bdL);background:var(--bgI);
  display:flex;align-items:baseline;justify-content:space-between;gap:6px}
.tsd-d{font-size:10.5px;font-weight:600}
.tsd-n{font-size:8.5px;color:var(--tx3);font-weight:600}
.tsd-io{font-size:9.5px;color:var(--tx3);font-weight:600;padding:0 10px 4px;
  font-variant-numeric:tabular-nums}
.tsd-b{padding:6px;flex:1;display:flex;flex-direction:column;gap:5px}
.tsd-e{border:1px solid var(--bdL);border-radius:7px;padding:5px 6px;
  background:var(--bgI);font-size:10px;line-height:1.35;cursor:pointer}
.tsd-e:hover{border-color:var(--ac)}
.tsd-e .p{display:block;font-weight:600;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.tsd-e .h{display:block;color:var(--tx3);font-weight:600;font-size:9px;margin-top:1px}
.tsd-f{padding:5px 6px;border-top:1px solid var(--bdL);font-size:9.5px;
  font-weight:600;color:var(--tx2);display:flex;justify-content:space-between}
.tsd-add{border:1px dashed var(--bd);border-radius:7px;padding:5px;font-size:10px;
  font-weight:600;color:var(--tx3);background:none;cursor:pointer;width:100%}
.tsd-add:hover{border-color:var(--ac);color:var(--ac)}
/* An empty day is one big target, not a thin dashed line at the top of a
   hole. The whole card is clickable then — the page wires the card's click
   to this button. */
.tsd-b .tsd-add:only-child{flex:1;display:flex;align-items:center;
  justify-content:center;min-height:72px;font-size:11px}
@media (max-width:900px){
  .tsg{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
}
@media (max-width:560px){
  .tsg{grid-template-columns:minmax(0,1fr)}
  .srch{display:none}
}

/* -- A month of days, for one person -------------------------------------- */
.mgrid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px}
.mgrid-h{font-size:10px;font-weight:500;color:var(--tx3);text-align:center;
  padding:2px 0}
.mday{aspect-ratio:1;border:1px solid var(--bdL);border-radius:8px;padding:4px;
  display:flex;flex-direction:column;justify-content:space-between;
  font-size:10px;background:var(--bg2);min-height:38px}
.mday.pad{border:none;background:none}
.mday .n{font-weight:600;font-size:10px}
.mday .m{font-size:9px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mday.s-present{background:var(--gnBg);border-color:transparent;color:var(--gn)}
.mday.s-wfh{background:var(--blBg);border-color:transparent;color:var(--bl)}
.mday.s-leave{background:var(--viBg);border-color:transparent;color:var(--vi)}
.mday.s-absent{background:var(--rdBg);border-color:transparent;color:var(--rd)}
.mday.s-half_day{background:var(--amBg);border-color:transparent;color:var(--am)}
.mday.s-week_off{background:var(--bgI);color:var(--tx3)}
.mday.s-holiday{background:var(--teBg);border-color:transparent;color:var(--te)}
.mday.today{outline:2px solid var(--ac);outline-offset:-1px}

/* -- A stack of things that happened, newest last -------------------------- */
.trail{list-style:none;margin:0;padding:0 0 0 20px;position:relative}
.trail::before{content:'';position:absolute;left:5px;top:6px;bottom:6px;
  border-left:1px solid var(--bd)}
.trail li{position:relative;padding:0 0 13px}
.trail li:last-child{padding-bottom:0}
.trail li::before{content:'';position:absolute;left:-18px;top:5px;width:7px;
  height:7px;border-radius:50%;background:var(--bg2);
  border:1.6px solid var(--tx3)}
.trail li.on::before{border-color:var(--ac);background:var(--ac)}
.trail .t{display:block;font-size:11.5px;font-weight:500}
.trail .s{display:block;font-size:9.5px;color:var(--tx3);font-weight:600;
  margin-top:1px}

/* -- Two numbers side by side, for a detail header ------------------------ */
.facts{display:flex;flex-wrap:wrap;gap:20px}
.fact .l{display:block;font-size:11px;font-weight:500;color:var(--tx3)}
.fact .v{display:block;font-size:15px;font-weight:600;letter-spacing:var(--ls-t);
  margin-top:2px}
.fact .v.sm{font-size:12.5px;display:block;border:0;border-radius:0;background:none;overflow:visible;margin-bottom:0}

/* A short list of consequences inside a confirm dialog. Used where a dialog
   has to state more than one thing that is true and cannot be a paragraph
   without becoming a wall. */
.bul{margin:0;padding:0 0 0 17px;font-size:12px;line-height:1.65;color:var(--tx2)}
.bul li{margin:0 0 4px}
.bul li:last-child{margin-bottom:0}


/* == 27. Going back ========================================================
   A named destination, not browser history. A page opened from a notification
   email has no history inside the product, and the browser's own back button
   takes the reader out of it entirely. */
.bk{display:inline-flex;align-items:center;gap:4px;font-size:9.5px;font-weight:600;
  color:var(--tx3);padding:2px 7px 2px 4px;margin:0 5px 0 -4px;border-radius:var(--r);
  border:1px solid transparent}
.bk:hover{color:var(--tx);background:var(--bg3);border-color:var(--bd);
  text-decoration:none}
.bk svg.i{width:12px;height:12px}

/* == 28. Announcement banners ==============================================
   Loud on purpose and rare on purpose. Tone is carried by a keyline down the
   left and by the icon colour — never by a filled block and never by anything
   that moves. A banner that shouts is a banner people learn to look past, and
   then the one that mattered is the one they looked past. */
.bnw{display:grid;gap:6px;margin-bottom:11px}
.bnw:empty{display:none}
/* The fold. Everything past the first notice lives behind one line, because
   a company with four live announcements used to push every screen in the
   product below the fold. */
.bn-more{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  padding:6px 11px;border:1px solid var(--bdL);border-radius:var(--rl);
  background:var(--bgI);color:var(--tx3);font:500 11px var(--f);cursor:pointer}
.bn-more:hover{border-color:var(--bd);color:var(--tx2)}
.bn-more svg.i{width:12px;height:12px;flex:none;transition:transform .15s}
.bn-more.on svg.i{transform:rotate(180deg)}
.bn-more>span:first-of-type{flex:none;font-weight:600}
.bn-more-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;opacity:.75}
.bn-rest{display:grid;gap:6px}
/* `display:grid` on the same element beats the user agent's `[hidden]`
   rule, so the fold rendered its contents at full height while claiming to
   be closed. Every `hidden` element that also carries a display in this file
   needs this line beside it. */
.bn-rest[hidden]{display:none}
/* How many identical notices folded into this one. */
.bn-n{display:inline-block;margin-left:7px;font-size:9.5px;font-weight:600;
  background:var(--bg3);color:var(--tx3);border-radius:var(--rp);
  padding:0 6px;vertical-align:middle}
/* A banner carries its tone as a wash and a coloured icon, not as a 3 px
   rail down its left edge. The rail was the one ribbon left in the kit, and
   on the home screen — where three notices stack — it read as a striped
   margin rather than as three separate levels. The tint says the same thing
   across the whole shape, which is also what makes it survive being read on
   a phone at a third of the width. */
.bn{display:flex;align-items:flex-start;gap:11px;padding:11px 14px;
  border:1px solid var(--bd);border-radius:var(--rl);
  background:var(--bg2);box-shadow:var(--sh)}
.bn-ic{flex:none;display:grid;place-items:center;width:20px;height:20px;
  color:var(--tx3)}
.bn-ic svg.i{width:15px;height:15px}
.bn-b{flex:1;min-width:0}
.bn-t{font-size:13px;font-weight:600;letter-spacing:0}
.bn-x{font-size:12px;color:var(--tx2);margin-top:4px;line-height:1.55;
  white-space:pre-wrap;overflow-wrap:anywhere}
.bn .btn{flex:none;align-self:center}
.bn-x-btn{flex:none;width:22px;height:22px;display:grid;place-items:center;
  border:none;background:none;color:var(--tx3);cursor:pointer;border-radius:5px}
.bn-x-btn:hover{background:var(--bg3);color:var(--tx)}
/* Three levels, and the strength is deliberately not uniform: a note is a
   wash, something that wants attention is a full tint, and something urgent
   also takes the border. A screen where every notice is coloured equally is
   a screen where the colour has stopped saying anything. */
.bn-i{background:color-mix(in srgb,var(--blBg) 60%,var(--bg2))}
.bn-i .bn-ic{color:var(--bl)}
.bn-a{background:var(--amBg);border-color:color-mix(in srgb,var(--am) 24%,var(--bd))}
.bn-a .bn-ic{color:var(--am)}
.bn-u{background:var(--rdBg);border-color:color-mix(in srgb,var(--rd) 40%,var(--bd))}
.bn-u .bn-ic{color:var(--rd)}
.bn-u .bn-t{color:var(--rd)}
/* The same three, in the accent, for a note that is neither a warning nor a
   piece of news — the security line on the joining form, most often. */
.bn-ac{background:var(--acBg);border-color:color-mix(in srgb,var(--ac) 22%,var(--bd))}
.bn-ac .bn-ic{color:var(--ac)}

/* == A chart that fills a card =============================================
   Two series of bars, a ceiling, a baseline and month labels. The SVG is
   drawn in its own 100-unit space and stretched, so the card can be any
   width; the axis labels sit outside it in real type, which is why they stay
   the right size when it stretches. */
.bc{display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:
  "y plot" ". legend";gap:0 9px}
.bc-y{grid-area:y;display:flex;flex-direction:column;justify-content:space-between;
  font-size:9px;font-weight:600;color:var(--tx3);text-align:right;
  font-variant-numeric:tabular-nums;padding:12px 0 15px}
.bc-p{grid-area:plot;min-width:0}
.bc-p svg{width:100%;height:132px;display:block;overflow:visible}
.bc-x{display:flex;justify-content:space-around;font-size:9px;font-weight:600;
  color:var(--tx3);margin-top:4px}
.bc-x span{flex:1;text-align:center;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.bc .lg2{grid-area:legend;margin-top:9px}

/* == Zoom and fill-the-screen ==============================================
   For anything drawn larger than the box it is in — a reporting line, a
   roster grid. The scale is a transform on the wrapper's child, so every
   anchor inside stays clickable and find-in-page keeps working. */
.zc{display:inline-flex;align-items:center;gap:2px;background:var(--bg2);
  border:1px solid var(--bd);border-radius:var(--rp);padding:2px;
  box-shadow:var(--sh)}
.zc .ico-btn{width:24px;height:24px;border-radius:50%}
.zc .ico-btn:disabled{opacity:.35;cursor:default;background:none}
.zc-v{border:0;background:none;font-family:var(--fm);font-size:10px;
  font-weight:500;color:var(--tx2);min-width:38px;cursor:pointer;
  padding:0 2px;font-variant-numeric:tabular-nums}
.zc-v:hover{color:var(--tx)}
.zc-sep{width:1px;height:14px;background:var(--bdL);margin:0 3px}

.zw{position:relative}
.zw > *{transition:transform .16s ease-out}

/* Taking over the window. Fixed rather than the Fullscreen API on purpose:
   the API needs a user gesture on the exact element, drops out of the page's
   own stacking context, and on a locked-down browser is simply refused. This
   always works and Escape always leaves. */
body.zfull-on{overflow:hidden}
.zw.zfull{position:fixed;inset:0;z-index:400;background:var(--bg2);
  padding:52px 16px 16px;overflow:auto;max-height:none;border-radius:0}
.zw.zfull > *{max-height:none}
/* Full screen has ONE scroller — the overlay itself. An inner list that
   keeps its own overflow draws a second scrollbar in the middle of the
   window and the tree pans in a letterbox instead of the screen. */
.zw.zfull .og{overflow:visible;max-height:none}
/* The floating controls while the window is taken over. Without them the
   only way out was knowing about Escape. */
.zfb{position:fixed;top:10px;right:14px;z-index:410;display:flex;gap:6px;
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rl);
  padding:5px;box-shadow:var(--shM)}
@media (prefers-reduced-motion:reduce){.zw > *{transition:none}}

/* == 29. SLA clocks ========================================================
   Two promises, side by side, so they are compared rather than read one at a
   time. The label is inside the chip because "4h left" on its own has been
   read as the wrong clock by everybody who has ever been shown it. */
.sla-w{display:inline-flex;gap:5px;flex-wrap:wrap;align-items:center}
.sla{display:inline-flex;align-items:center;gap:5px;font-size:9.5px;font-weight:600;
  padding:2px 7px;border-radius:var(--rp);border:1px solid var(--bd);
  background:var(--bgI);color:var(--tx2);white-space:nowrap;
  font-variant-numeric:tabular-nums}
.sla b{font-weight:500;color:var(--tx3);font-size:9.5px}
.sla-ok{background:var(--gnBg);border-color:transparent;color:var(--gn)}
.sla-ok b{color:var(--gn);opacity:.75}
.sla-live{background:var(--blBg);border-color:transparent;color:var(--bl)}
.sla-live b{color:var(--bl);opacity:.75}
.sla-soon{background:var(--amBg);border-color:transparent;color:var(--am)}
.sla-soon b{color:var(--am);opacity:.75}
.sla-late{background:var(--rdBg);border-color:transparent;color:var(--rd)}
.sla-late b{color:var(--rd);opacity:.75}
.sla-none{color:var(--tx3)}
/* The two clocks stacked, on a detail page where there is room to name them. */
.slabox{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:9px}
@media(max-width:640px){.slabox{grid-template-columns:minmax(0,1fr)}}
.slabox .sb-i{border:1px solid var(--bd);border-radius:var(--rl);padding:10px 12px;
  background:var(--bg2)}
.slabox .sb-l{font-size:11px;font-weight:500;color:var(--tx3)}
.slabox .sb-v{font-size:17px;font-weight:600;letter-spacing:-.015em;margin-top:5px;
  font-variant-numeric:tabular-nums}
.slabox .sb-s{font-size:9.5px;color:var(--tx3);font-weight:600;margin-top:3px}
.slabox .sb-i.late{border-color:var(--rd)} .slabox .sb-i.late .sb-v{color:var(--rd)}
.slabox .sb-i.ok .sb-v{color:var(--gn)}
.slabox .sb-i.soon .sb-v{color:var(--am)}

/* == 30. Month calendar ====================================================
   One month as weeks. Built in the kit rather than per screen because three
   screens want it and three copies of date arithmetic is three chances to be
   a day out. */
.cal{border:1px solid var(--bd);border-radius:var(--rx);overflow:hidden;
  background:var(--bg2)}
.cal-hd{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));background:var(--bgI);
  border-bottom:1px solid var(--bd)}
.cal-hd div{padding:7px 9px;font-size:10.5px;font-weight:500;color:var(--tx3)}
.cal-g{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}
.cal-d{min-height:96px;padding:6px 7px;border-right:1px solid var(--bdL);
  border-bottom:1px solid var(--bdL);display:flex;flex-direction:column;gap:3px;
  min-width:0}
.cal-d:nth-child(7n){border-right:0}
.cal-d.out{background:var(--bgI)}
.cal-d.off{background:var(--bgI)}
.cal-d.now{background:var(--acBg);box-shadow:inset 0 0 0 1px var(--ac)}
.cal-d[role=button]{cursor:pointer}
.cal-d[role=button]:hover{background:var(--bg3)}
.cal-n{font-size:11px;font-weight:600;color:var(--tx2);
  font-variant-numeric:tabular-nums;line-height:1.2}
.cal-d.now .cal-n{color:var(--ac)}
.cal-d.out .cal-n{display:none}
/* An entry is a line of text on a tint, not a coloured bar with a tooltip:
   the point of a calendar is reading it without hovering anything. */
.cal-e{display:block;font-size:9.5px;font-weight:500;padding:2px 6px;
  border-radius:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cal-e.me{font-weight:600}
.cal-more{font-size:8.5px;color:var(--tx3);font-weight:600;padding-left:2px}
.cal-gn{background:var(--gnBg);color:var(--gn)}
.cal-vi{background:var(--viBg);color:var(--vi)}
.cal-bl{background:var(--blBg);color:var(--bl)}
.cal-or{background:var(--orBg);color:var(--or)}
.cal-te{background:var(--teBg);color:var(--te)}
.cal-ac{background:var(--acBg);color:var(--ac)}
.cal-am{background:var(--amBg);color:var(--am)}
.cal-rd{background:var(--rdBg);color:var(--rd)}
.cal-gy{background:var(--bg3);color:var(--tx2)}
@media(max-width:880px){
  .cal-d{min-height:70px;padding:4px 5px}
  .cal-e{font-size:8.5px;padding:1px 4px}
}
/* The legend. Named colours, once, so nothing on the grid needs a caption. */
.cal-key{display:flex;flex-wrap:wrap;gap:5px 14px;padding:9px 2px 0;
  font-size:9.5px;font-weight:600;color:var(--tx3)}
.cal-key span{display:inline-flex;align-items:center;gap:6px}
.cal-key i{width:9px;height:9px;border-radius:3px;display:block}

/* == 31. Meter =============================================================
   Against a quota. Says both numbers and then draws the ratio — never the
   ratio alone, because a per cent of an unstated total is not actionable. */
.mt{margin-bottom:11px}
.mt:last-child{margin-bottom:0}
.mt-h{display:flex;justify-content:space-between;align-items:baseline;gap:9px;
  font-size:10.5px;font-weight:500;color:var(--tx2);margin-bottom:5px}
.mt-v{font-size:10.5px;font-weight:600;color:var(--tx);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.mt-b{height:6px;border-radius:3px;background:var(--bg3);overflow:hidden}
.mt-b i{display:block;height:100%;background:var(--ac);border-radius:3px;
  transition:width .3s}
.mt.high .mt-b i{background:var(--am)}
.mt.high .mt-v{color:var(--am)}
.mt.full .mt-b i{background:var(--rd)}
.mt.full .mt-v{color:var(--rd)}

/* == 32. Permission picker =================================================
   Fifty-eight codes and a checkbox each was a screen that could only be used
   by somebody who already knew the answer. Every row now says what it does,
   which screens it opens, and whether it is one to be careful with. */
.pm-p{border:1px solid var(--bd);border-radius:var(--rl);margin-bottom:9px;
  overflow:hidden;background:var(--bg2)}
.pm-h{display:flex;align-items:center;gap:9px;padding:9px 12px;background:var(--bgI);
  border-bottom:1px solid var(--bd);cursor:pointer}
.pm-h:hover{background:var(--bg3)}
.pm-nm{font-size:11.5px;font-weight:600;flex:1;min-width:0}
.pm-ct{font-size:9.5px;font-weight:600;color:var(--tx3);
  font-variant-numeric:tabular-nums}
.pm-l{padding:2px 0}
.pm-i{display:flex;align-items:flex-start;gap:11px;padding:9px 12px;
  border-top:1px solid var(--bdL);cursor:pointer}
.pm-i:first-child{border-top:0}
.pm-i:hover{background:var(--bgI)}
.pm-i input{margin-top:2px;accent-color:var(--ac);width:14px;height:14px;flex:none}
.pm-b{flex:1;min-width:0}
.pm-t{font-size:11.5px;font-weight:500;display:flex;align-items:center;gap:7px;
  flex-wrap:wrap}
.pm-w{font-size:10.5px;color:var(--tx2);margin-top:3px;line-height:1.55}
.pm-where{font-size:9.5px;color:var(--tx3);margin-top:4px;font-weight:600}
.pm-code{font-family:var(--fm);font-size:9px;color:var(--tx3)}
/* Marked, not hidden. A permission an administrator cannot find is one they
   will grant by making somebody an owner instead. */
.pm-care{font-size:8.5px;font-weight:600;color:var(--am);background:var(--amBg);
  border-radius:var(--rp);padding:1px 7px;letter-spacing:.3px;white-space:nowrap}
.pm-i.no{opacity:.5}
.pm-i.no input{cursor:not-allowed}
.pm-no{font-size:8.5px;font-weight:600;color:var(--tx3);background:var(--bg3);
  border-radius:var(--rp);padding:1px 7px;white-space:nowrap}

/* == 33. Role cards ========================================================
   A starting point for a group, shown as what it lets somebody do rather than
   as a list of codes. */
.rl{display:grid;grid-template-columns:repeat(auto-fill,minmax(272px,1fr));gap:10px}
.rl-c{border:1px solid var(--bd);border-radius:var(--rl);padding:13px 14px;
  background:var(--bg2);display:flex;flex-direction:column;min-width:0}
.rl-c:hover{border-color:var(--ac)}
.rl-t{font-size:12.5px;font-weight:600;display:flex;align-items:center;gap:8px}
.rl-d{font-size:10.5px;color:var(--tx2);margin-top:5px;line-height:1.55;flex:1}
.rl-does{display:flex;flex-wrap:wrap;gap:4px;margin-top:9px}
.rl-does span{font-size:9px;font-weight:500;background:var(--bg3);color:var(--tx2);
  border-radius:var(--rp);padding:2px 8px}
.rl-f{display:flex;align-items:center;gap:6px;margin-top:11px;
  padding-top:10px;border-top:1px solid var(--bdL)}
.rl-f .btn{flex:none;padding:0 8px}
.rl-n{font-size:9.5px;color:var(--tx3);font-weight:600;flex:1;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* == 34. Job cards =========================================================
   An opening, from the inside. */
.jb{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:10px}
.jb-c{border:1px solid var(--bd);border-radius:var(--rx);padding:14px 15px;
  background:var(--bg2);display:flex;flex-direction:column;min-width:0;
  box-shadow:var(--sh)}
.jb-c:hover{border-color:var(--ac);box-shadow:var(--shM)}
.jb-t{font-size:13.5px;font-weight:600;letter-spacing:0;line-height:1.3}
.jb-m{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:6px;font-size:10.5px;
  color:var(--tx3);font-weight:600}
.jb-m span{display:inline-flex;align-items:center;gap:5px}
.jb-s{display:flex;flex-wrap:wrap;gap:4px;margin-top:10px}
.jb-s span{font-size:9.5px;font-weight:500;background:var(--bg3);color:var(--tx2);
  border-radius:var(--rp);padding:2px 8px}
.jb-f{display:flex;align-items:center;gap:7px;margin-top:12px;padding-top:11px;
  border-top:1px solid var(--bdL)}
.jb-rw{font-size:10px;font-weight:600;color:var(--gn);flex:1}

/* == 35. Card content, straightened ========================================
   Three shapes that were laying out wrong wherever they appeared.

   Two spans in a flex row render on one line, which is how "Farhan
   ShaikhSite Engineer" got onto four screens. The kit now owns the fix rather
   than each page discovering it again. */
.x-n,.x-s{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.x-n{font-weight:500;font-size:11.5px}
.x-s{font-size:10px;color:var(--tx3);font-weight:600}
/* A definition grid whose last row has a right border on the last cell, and a
   ragged bottom edge where the row did not fill. Both are the same fix. */
.dv-i:last-child{border-right:0}
.dv-i{display:flex;flex-direction:column;justify-content:flex-start}
/* A card body whose children are cards should not double its own padding. */
.cd-bd > .cd:last-child{margin-bottom:0}
.cd-bd > .g2:last-child,.cd-bd > .g3:last-child{margin-bottom:0}
/* A card header where the title block and the actions collide at narrow
   widths: the title keeps its line, the actions wrap under it. */
.cd-h > div:first-child{min-width:0;flex:1}
.cd-t{min-width:0;overflow-wrap:anywhere}
.cd-s{overflow-wrap:anywhere}
/* Long values inside a facts grid have to wrap, not push the column open —
   an IFSC or a 200-character note was widening the whole card. */
.kv dd,.dv-v{overflow-wrap:anywhere}

/* == 36. Page sections =====================================================
   A heading with a rule to its right, for a page that has grown past one
   card. `.sec-t` already did this inside a modal; this is its page-level
   twin, with room above it. */
.pg-sec{display:flex;align-items:center;gap:10px;margin:20px 0 10px;
  font-size:11px;font-weight:600;color:var(--tx2);letter-spacing:0}
.pg-sec::after{content:"";flex:1;height:1px;background:var(--bd)}
.pg-sec:first-child{margin-top:0}
.pg-sec .ct{font-size:9.5px;color:var(--tx3);font-weight:600}

/* == 37. A thread ==========================================================
   Two sides talking. Used by the support desk on both planes, and by the
   request desks. Whose message it is has to be answerable at a glance from
   the shape alone, because the names on it are unfamiliar in both
   directions. */
.th{display:grid;gap:10px}
.th-m{display:flex;gap:10px;max-width:min(760px,100%)}
.th-m.mine{margin-left:auto;flex-direction:row-reverse}
.th-av{width:28px;height:28px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-size:9.5px;font-weight:600;color:#fff}
.th-b{border:1px solid var(--bd);border-radius:var(--rl);padding:10px 13px;
  background:var(--bg2);min-width:0}
.th-m.mine .th-b{background:var(--acBg);border-color:transparent}
.th-h{display:flex;align-items:baseline;gap:9px;margin-bottom:4px;flex-wrap:wrap}
.th-who{font-size:11px;font-weight:600}
.th-at{font-size:9.5px;color:var(--tx3);font-weight:600}
.th-t{font-size:12px;line-height:1.6;white-space:pre-wrap;overflow-wrap:anywhere}
/* Effred talking to Effred. Never crosses to the customer's side, and it has
   to be obvious on the screen that it will not. */
.th-m.note .th-b{background:var(--amBg);border-color:var(--am);border-style:dashed}
.th-tag{font-size:10px;font-weight:500;color:var(--am)}

/* == 38. A summary strip ===================================================
   Facts about one record, across the top of its page. Denser than KPI tiles
   and quieter: these are not measurements, they are what the record is. */
.sm{display:flex;flex-wrap:wrap;gap:0;border:1px solid var(--bd);
  border-radius:var(--rl);background:var(--bg2);overflow:hidden;margin-bottom:11px}
.sm-i{padding:10px 15px;border-right:1px solid var(--bdL);min-width:132px;flex:1}
.sm-i:last-child{border-right:0}
.sm-l{font-size:12px;font-weight:500;color:var(--tx3);letter-spacing:0}
.sm-v{font-size:13.5px;font-weight:600;margin-top:3px;letter-spacing:0;
  overflow-wrap:anywhere}
.sm-v.big{font-size:19px}
@media(max-width:700px){.sm-i{min-width:50%;flex:none;
  border-bottom:1px solid var(--bdL)}}


/* A figure that goes somewhere.
   -------------------------------------------------------------------------
   Used by the head-room meters on the control plane. Every number on that
   page was a dead end — it said "11 of 1000" and finding which eleven meant
   opening the customer's portal in another tab and hunting for the screen.
   The whole block is the target, because a number is what people aim at. */
.mtr{display:block;color:var(--tx);border-radius:var(--rl);padding:2px;
  margin:-2px;transition:background .12s}
.mtr:hover{background:var(--bgI);text-decoration:none}
.mtr:hover .ki-v{color:var(--ac)}

/* == 39. The greeting strip ================================================
   The first thing on My space: who you are, what today is, and the three
   things people came here to do.

   It replaced a page header. A page header names the page, which on somebody's
   own home screen is the one fact they already have — they clicked the thing
   that brought them here. What they do not have is whether the timesheet is
   due, so the strip carries the actions rather than a title. */
.hail{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;
  margin-bottom:16px}
.hail-l{flex:1;min-width:240px}
.hail-h{font-size:24px;font-weight:600;letter-spacing:var(--ls-h);line-height:1.15}
.hail-s{font-size:12px;color:var(--tx3);font-weight:500;margin-top:5px;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.hail-s .dt{opacity:.45}
.hail-a{display:flex;align-items:center;gap:8px;flex-wrap:wrap}

/* == 40. An agenda =========================================================
   A day as a column of times. Used by the schedule card on My space, by the
   calendar screen, and by the technician's day.

   The rail down the left is a 1 px hairline with a dot per row, not a bar —
   it says these are in order and stops there. `.now` is the row happening at
   this minute and is the only one that carries the accent, because a day
   where four rows are highlighted has told nobody which one is next. */
.agd{display:grid;gap:0;position:relative}
.agd-r{display:grid;grid-template-columns:62px 12px minmax(0,1fr) auto;gap:11px;
  align-items:flex-start;padding:11px 0;border-bottom:1px solid var(--bdL);
  min-width:0}
.agd-r:last-child{border-bottom:0}
.agd-t{font-size:11px;font-weight:600;color:var(--tx3);
  font-variant-numeric:tabular-nums;padding-top:1px;white-space:nowrap}
/* The dot and the thread it hangs on. Drawn on the marker so a row that is
   the last one does not trail a line into nothing. */
.agd-m{position:relative;width:12px;align-self:stretch;display:flex;
  justify-content:center;padding-top:4px}
.agd-m::before{content:"";position:absolute;top:0;bottom:-11px;width:1px;
  background:var(--bdL)}
.agd-r:last-child .agd-m::before{display:none}
.agd-m i{position:relative;width:8px;height:8px;border-radius:50%;
  background:var(--bd);box-shadow:0 0 0 3px var(--bg2);flex:none}
/* One hue per meeting, hashed off its subject so the same standup is the same
   colour every morning. It is the only thing distinguishing six rows of
   identical shape, and a column of identical grey dots is a column nobody
   scans. */
.agd-m i.c0{background:var(--g-bl)} .agd-m i.c1{background:var(--g-vi)}
.agd-m i.c2{background:var(--g-te)} .agd-m i.c3{background:var(--g-am)}
.agd-m i.c4{background:var(--g-gn)} .agd-m i.c5{background:var(--g-rd)}
.agd-b{min-width:0}
.agd-n{display:block;font-size:12.5px;font-weight:600;
  letter-spacing:0;overflow-wrap:anywhere}
.agd-s{font-size:10.5px;color:var(--tx3);font-weight:500;margin-top:3px;
  display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.agd-x{display:flex;align-items:center;gap:7px;flex:none;padding-top:1px}
.agd-r.done .agd-n{color:var(--tx3)}
.agd-r.done .agd-m i{background:var(--gn)}
.agd-r.now .agd-m i{background:var(--ac);box-shadow:0 0 0 3px var(--acBg)}
.agd-r.now{background:var(--acBg);border-radius:var(--rl);
  padding-left:11px;padding-right:11px;margin:0 -11px;border-bottom-color:transparent}
.agd-r.now .agd-n{color:var(--acD)}
/* A meeting somebody can walk into from here. The button is only drawn when
   there is somewhere to go — a Join that opens nothing is exactly the control
   §4 rules out. */
.agd .jn{flex:none}
@media(max-width:560px){
  .agd-r{grid-template-columns:54px 12px minmax(0,1fr);row-gap:6px}
  .agd-x{grid-column:3;justify-content:flex-start}
}

/* == 41. What is waiting on somebody ======================================
   Two lists that look alike and mean opposite things: things this person has
   to do, and things they are waiting for somebody else to do. Told apart by
   the heading over each and by the second having a face on it — the face is
   whose desk it is sitting on, which is the only fact that makes waiting
   bearable. */
.tsk{display:grid;gap:0}
.tsk-r{display:flex;align-items:flex-start;gap:11px;padding:11px 0;
  border-bottom:1px solid var(--bdL);min-width:0}
.tsk-r:last-child{border-bottom:0}
.tsk-i{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  flex:none;background:var(--bg3);color:var(--tx2)}
.tsk-i svg.i{width:15px;height:15px}
.tsk-i.am{background:var(--amBg);color:var(--am)}
.tsk-i.rd{background:var(--rdBg);color:var(--rd)}
.tsk-i.ac{background:var(--acBg);color:var(--ac)}
.tsk-b{flex:1;min-width:0}
.tsk-n{display:block;font-size:12.5px;font-weight:600;
  letter-spacing:0;overflow-wrap:anywhere}
.tsk-s{display:block;font-size:10.5px;color:var(--tx3);font-weight:500;
  margin-top:3px}
.tsk-x{flex:none;display:flex;align-items:center;gap:7px;padding-top:3px}
.tsk-w{font-size:10px;font-weight:600;color:var(--tx3);white-space:nowrap}
.tsk-w.due{color:var(--am)} .tsk-w.late{color:var(--rd)}

/* == 42. Who is around =====================================================
   A row of faces and then the names under it. The faces answer how many and
   the names answer who, and both were asked for often enough on the same card
   to be one component. */
.fstack{display:flex;align-items:center;padding-left:6px}
.fstack > *{margin-left:-6px;border:2px solid var(--bg2);flex:none}
.fstack .more{width:30px;height:30px;border-radius:50%;background:var(--bg3);
  color:var(--tx2);display:grid;place-items:center;font-size:9.5px;
  font-weight:600}
.prs{display:grid;gap:0;margin-top:12px}
.prs-r{display:flex;align-items:center;gap:9px;padding:7px 0;
  border-bottom:1px solid var(--bdL);font-size:12px;min-width:0}
.prs-r:last-child{border-bottom:0}
.prs-r .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-weight:500}
/* A presence dot. Four states and no animation: a pulsing dot on a screen
   somebody keeps open all day is a thing that moves in the corner of their
   eye for eight hours. */
.pdot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--g-gy)}
.pdot.in{background:var(--g-gn)} .pdot.rm{background:var(--g-bl)}
.pdot.busy{background:var(--g-am)} .pdot.off{background:var(--g-gy)}

/* == 43. Dates as chips ====================================================
   A holiday, an anniversary, a renewal — anything that is a date and a
   sentence. The month sits over the day so the column stays 40 px wide
   whatever the length of the month name. */
.dchip{display:flex;align-items:center;gap:11px;padding:9px 0;
  border-bottom:1px solid var(--bdL);min-width:0}
.dchip:last-child{border-bottom:0}
.dchip .cal{width:40px;flex:none;border:1px solid var(--bd);border-radius:9px;
  overflow:hidden;text-align:center;background:var(--bg2)}
.dchip .cal .mo{font-size:8px;font-weight:600;letter-spacing:.6px;
  background:var(--bg3);color:var(--tx3);padding:2px 0}
.dchip .cal .dy{font-size:14px;font-weight:600;letter-spacing:-.01em;
  padding:3px 0 4px;line-height:1}
.dchip.soon .cal .mo{background:var(--acBg);color:var(--acD)}
.dchip .db{min-width:0;flex:1}
.dchip .dn{display:block;font-size:12px;font-weight:600;
  overflow-wrap:anywhere}
.dchip .ds{display:block;font-size:10.5px;color:var(--tx3);
  font-weight:500;margin-top:2px}

/* == 44. The clock card ====================================================
   Check in, check out, and how long you have been here. One figure, one
   sentence, one button — anything else on this card is a thing somebody has
   to read past twice a day for the rest of their employment. */
.clk{text-align:center;padding:6px 0 2px}
.clk-t{font-size:36px;font-weight:600;letter-spacing:-.025em;line-height:1;
  font-variant-numeric:tabular-nums}
.clk-t .ap{font-size:15px;font-weight:600;color:var(--tx3);letter-spacing:0;
  margin-left:5px}
.clk-s{font-size:11px;color:var(--tx3);font-weight:500;margin-top:8px}
.clk-m{display:flex;justify-content:center;gap:9px;flex-wrap:wrap;
  margin-top:12px;font-size:10px;font-weight:600;color:var(--tx3)}
.clk-m span{background:var(--bgI);border:1px solid var(--bd);
  border-radius:var(--rp);padding:3px 10px}

/* == 45. A checklist of paper =============================================
   What somebody still owes, and what has been looked at. Used by the
   onboarding review and by the joiner's own upload page, which is why the row
   has to read the same whether or not there is a file behind it. */
.plist{display:grid;gap:0}
.pl-r{display:flex;align-items:center;gap:11px;padding:11px 0;
  border-bottom:1px solid var(--bdL);min-width:0}
.pl-r:last-child{border-bottom:0}
.pl-m{width:22px;height:22px;border-radius:7px;flex:none;display:grid;
  place-items:center;background:var(--bg3);color:var(--tx3)}
.pl-m svg.i{width:12px;height:12px}
.pl-m.ok{background:var(--gnBg);color:var(--gn)}
.pl-m.no{background:var(--rdBg);color:var(--rd)}
.pl-m.wait{background:var(--amBg);color:var(--am)}
.pl-b{flex:1;min-width:0}
/* Both declared block. `<span class="pl-n">` and `<span class="pl-s">`
   inside a flex child render on one line — "Photo IDaadhaar.pdf" — and
   that is the mistake CLAUDE.md §10 lists as "two spans that should
   stack", caught six times before this one. Fixed on the component
   rather than on the caller, so it cannot come back whichever element
   somebody reaches for. */
.pl-n{display:block;font-size:12.5px;font-weight:600;
  overflow-wrap:anywhere}
.pl-s{display:block;font-size:10.5px;color:var(--tx3);font-weight:500;
  margin-top:2px;overflow-wrap:anywhere}
.pl-x{flex:none;display:flex;align-items:center;gap:6px}
/* A drop target. It is a label wrapping a file input, so the whole box is the
   control and the keyboard reaches it — a div with a click handler is
   neither. */
.drop{display:flex;align-items:center;justify-content:center;gap:9px;
  padding:18px;border:1.5px dashed var(--bd);border-radius:var(--rl);
  background:var(--bgI);color:var(--tx3);font-size:12px;font-weight:500;
  cursor:pointer;text-align:center;transition:border-color .14s,background .14s}
.drop:hover,.drop.over{border-color:var(--ac);background:var(--acBg);
  color:var(--acD)}
.drop input[type=file]{display:none}

/* == 46. A public page =====================================================
   The onboarding form a new joiner opens from a link in their mail, and the
   quotation a customer accepts. Neither person has a login, neither has ever
   seen this product, and both arrived from an email — so the page says whose
   it is at the top and carries no navigation at all, because there is nowhere
   else they may go. */
.pub{min-height:100vh;background:var(--bg);padding:0 0 40px}
.pub-h{background:var(--bg2);border-bottom:1px solid var(--bd);padding:16px 20px}
.pub-hi{max-width:940px;margin:0 auto;display:flex;align-items:center;gap:12px;
  flex-wrap:wrap}
.pub-c{max-width:940px;margin:0 auto;padding:24px 20px 0}
.pub-c.narrow{max-width:640px}
/* The steps across the top of a form somebody fills in once. Numbers, a line
   between them, and the one they are on in the accent. */
.stps{display:flex;align-items:center;gap:0;margin-bottom:20px;overflow-x:auto;
  scrollbar-width:none}
.stps::-webkit-scrollbar{display:none}
.jst{display:flex;align-items:center;gap:9px;flex:none;padding-right:14px}
.jst .n{width:26px;height:26px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-size:11px;font-weight:600;background:var(--bg3);
  color:var(--tx3)}
.jst .l{font-size:11.5px;font-weight:500;color:var(--tx3);white-space:nowrap}
.jst.on .n{background:var(--ac);color:var(--acTx,#fff)}
.jst.on .l{color:var(--tx);font-weight:600}
.jst.done .n{background:var(--gnBg);color:var(--gn)}
.jst.done .l{color:var(--tx2)}
.jst::after{content:"";width:26px;height:1px;background:var(--bd);
  margin-left:14px;flex:none}
.jst:last-child{padding-right:0}
.jst:last-child::after{display:none}
@media(max-width:640px){.jst .l{display:none}.jst::after{width:16px;margin-left:8px}}

/* == 47. A link somebody was sent ==========================================
   One row per invitation: who it went to, where it got to, and when it stops
   working. The token itself is never drawn — it is in their mail, and a link
   on a screen behind a shoulder is a link that has left the building. */
.lnk-r{display:flex;align-items:center;gap:11px;padding:11px 0;
  border-bottom:1px solid var(--bdL);min-width:0}
.lnk-r:last-child{border-bottom:0}
.lnk-b{flex:1;min-width:0}
.lnk-n{display:block;font-size:12.5px;font-weight:600;
  overflow-wrap:anywhere}
.lnk-s{font-size:10.5px;color:var(--tx3);font-weight:500;margin-top:2px;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.lnk-x{flex:none;display:flex;align-items:center;gap:7px}


/* == 48. A week of hours, as bars =========================================
   Seven columns, today marked. It is the same data the KPI tile draws as a
   sparkline, at the size where the individual days are readable — the tile
   answers "how is the week going", this answers "which day am I short on".

   The bar grows from the bottom of a fixed-height track rather than the
   column being the bar, so seven days of wildly different hours still line
   their labels up. A day with no hours gets no number rather than a nought:
   nought reads as "I worked zero hours" and blank reads as "not yet", and on
   a Wednesday the difference is the whole point. */
.wkb{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;align-items:end}
.wkb-c{display:flex;flex-direction:column;align-items:center;gap:5px;min-width:0}
.wkb-v{font-size:10px;font-weight:600;color:var(--tx3);height:12px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.wkb-t{width:100%;height:66px;background:var(--bg3);border-radius:6px;
  display:flex;align-items:flex-end;overflow:hidden}
.wkb-t i{display:block;width:100%;background:var(--g-bl);border-radius:6px}
.wkb-d{font-size:9.5px;font-weight:600;color:var(--tx3);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:100%}
/* Today is the one column that carries the accent. A week where every bar is
   coloured has told nobody which day they are standing in. */
.wkb-c.on .wkb-t i{background:var(--ac)}
.wkb-c.on .wkb-d,.wkb-c.on .wkb-v{color:var(--acD)}

/* == 49. A face ===========================================================
   One avatar, used in the stack on the presence card and beside a name in a
   list. Square-ratio, round, and it never distorts a photograph — the
   difference between `object-fit:cover` and the default is a room full of
   people who look slightly wrong. */
.fs-a{width:30px;height:30px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-size:10.5px;font-weight:600;color:#fff;
  overflow:hidden;object-fit:cover}
.fs-a.sm{width:26px;height:26px;font-size:9.5px}
img.fs-a{object-fit:cover}

/* == 50. One figure on its own ============================================
   The last payslip. A number this size is read from across a desk, which is
   the only reason anything in this product is allowed to be 26 px. */
.paybox{background:var(--bgI);border:1px solid var(--bd);border-radius:var(--rl);
  padding:12px 14px;margin-bottom:12px}
.pay-v{font-size:26px;font-weight:600;letter-spacing:var(--ls-n);line-height:1.1;
  margin-top:5px;font-variant-numeric:tabular-nums}


/* == 51. A stacked bar ====================================================
   One bar, several kinds, a legend under it. The leave card had one row per
   type with its own track, which is four bars answering a question — "how
   much have I got left" — that is really one number split several ways.

   The hues are positional rather than semantic: leave type one is always the
   first hue, on every screen, for every company. Nothing here means "good" or
   "bad", so nothing here borrows the tones that do. */
.stk{display:flex;height:9px;border-radius:var(--rp);overflow:hidden;
  background:var(--bg3);margin:4px 0 11px}
.stk i{display:block;height:100%;min-width:3px}
.stk i.k0{background:var(--g-gn)} .stk i.k1{background:var(--g-am)}
.stk i.k2{background:var(--g-vi)} .stk i.k3{background:var(--g-bl)}
.stk i.k4{background:var(--g-te)} .stk i.k5{background:var(--g-rd)}
.stk-l{display:flex;flex-wrap:wrap;gap:6px 14px}
.stk-l span{display:inline-flex;align-items:center;gap:6px;font-size:10.5px;
  font-weight:500;color:var(--tx2)}
.stk-l i{width:8px;height:8px;border-radius:50%;flex:none}
.stk-l i.k0{background:var(--g-gn)} .stk-l i.k1{background:var(--g-am)}
.stk-l i.k2{background:var(--g-vi)} .stk-l i.k3{background:var(--g-bl)}
.stk-l i.k4{background:var(--g-te)} .stk-l i.k5{background:var(--g-rd)}
.stk-l b{font-weight:600;color:var(--tx)}

/* A celebration. Pink for a birthday and violet for an anniversary — the two
   are read at a glance from across the card, and neither borrows a tone that
   means something elsewhere. */
.cel-i{width:30px;height:30px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-size:10.5px;font-weight:600}
.cel-i.bd{background:#FBEAF1;color:#A83862}
.cel-i.an{background:var(--viBg);color:var(--vi)}
.cel-w{font-size:10.5px;font-weight:600;white-space:nowrap}
.cel-w.bd{color:#A83862} .cel-w.an{color:var(--vi)}


/* == 52. The deck =========================================================
   A home screen laid out as a wrapping row of fixed-height cards.

   This replaces the two-column split My space used to run on. That split was
   ragged by construction — two independent stacks end at different heights
   and the difference is a hole — and a masonry flow fixed the hole by making
   the reading order jump columns. Neither is what a dashboard wants.

   The deck is one flex row that wraps. Each card declares how greedy it is
   (`--gw`, the flex-grow) and how narrow it may get before wrapping (`--mw`),
   so a card that is mostly a list can sit beside one that is mostly a number
   and neither has to be the same width. `align-items:stretch` plus a height
   on the card is what makes every row end level whatever is in it.

   The heights are deliberate and they are the whole trick: a card is a fixed
   box with its own scroll, so a week with forty meetings in it renders the
   same shape as a week with two, and the cards below never move. A dashboard
   whose layout changes with the data is one nobody builds a habit around. */
.deck{display:flex;flex-wrap:wrap;gap:14px;align-items:stretch;
  margin-bottom:14px}
.deck > .dk{flex:var(--gw,1) 1 var(--fb,280px);min-width:var(--mw,260px);
  height:var(--h,280px);background:var(--bg2);border:1px solid var(--bd);
  border-radius:var(--rx);padding:16px 18px;display:flex;flex-direction:column;
  min-height:0;overflow:hidden}
/* The head is fixed and the body scrolls under it. Both are load-bearing:
   without `flex-shrink:0` on the head a long list squeezes the title away,
   and without `min-height:0` on the body the scroll never engages, because a
   flex item's default floor is its content. */
.dk-h{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-bottom:12px;flex-shrink:0}
.dk-t{font-size:14px;font-weight:var(--w-t);letter-spacing:0}
.dk-b{flex:1;min-height:0;overflow-y:auto;
  display:flex;flex-direction:column;gap:9px;padding-bottom:4px;
  /* Scrolls, and does not draw a bar to say so. Thirteen cards each with a
     6 px groove down the right edge is thirteen vertical lines on a screen
     whose whole point is that it reads as one surface. Wheel, trackpad,
     keyboard and touch are all untouched; only the gutter is gone, and
     `overscroll-behavior` stops a flick inside a card carrying on into the
     page behind it. */
  /* No `overscroll-behavior:contain` here, deliberately. A scroll container
     carrying it is a scroll BOUNDARY even when its content fits, so with
     thirteen cards tiling the screen the page itself stopped scrolling the
     moment the cursor was over any of them — which is most of the screen.
     Standard chaining is right: a card scrolls to its end, then the page
     carries on. */
  scrollbar-width:none;-ms-overflow-style:none}
.dk-b::-webkit-scrollbar{width:0;height:0;display:none}
.dk-b.plain{display:block}
/* Pushes whatever follows to the bottom of the card, so a footer sits on the
   floor rather than under the last row. */
.dk-sp{flex:1;min-height:0}
.dk-f{flex-shrink:0;padding-top:10px;font-size:11.5px;color:var(--tx3);
  font-weight:500}
/* A card whose height is genuinely its content — the KPI strip. */
.deck.auto > .dk{height:auto}
@media(max-width:700px){
  .deck > .dk{height:auto;max-height:none}
  .dk-b{overflow:visible}
}

/* == 53. The clock card ===================================================
   The one card on the home screen that is a control rather than a report, and
   the only card in the product that is not white.

   That is on purpose and it is the exception that proves the rule: everything
   else here is something to read, this is the thing most of the company opens
   the portal to press twice a day. Making it the one coloured object on the
   screen is what lets somebody find it without looking. The two rings are
   drawn at 7-9% white — visible as depth, never as decoration competing with
   the figure. */
.dk.clock{background:var(--acD);border-color:transparent;color:#fff;
  position:relative;overflow:hidden}
.dk.clock .dk-t{color:#fff}
.dk.clock > *{position:relative}
.ck-pill{display:inline-flex;align-items:center;gap:6px;
  background:rgba(255,255,255,.16);border-radius:var(--rp);padding:4px 10px;
  font-size:11.5px;font-weight:600;white-space:nowrap}
.ck-pill i{width:7px;height:7px;border-radius:50%;background:#7DF0BE;flex:none}
.ck-pill.off i{background:#FFD166}
.ck-t{text-align:center;margin:16px 0 4px}
.ck-n{font-size:40px;font-weight:600;letter-spacing:-.025em;line-height:1;
  font-variant-numeric:tabular-nums}
.ck-n span{font-size:17px;font-weight:600;opacity:.85;letter-spacing:0}
.ck-s{font-size:12.5px;font-weight:500;opacity:.85;margin-top:8px}
.ck-m{display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap;
  font-size:11.5px;font-weight:500;opacity:.85;margin-bottom:12px}
.ck-go{background:#fff;color:var(--acD);border:none;border-radius:var(--r);
  padding:10px;font-family:var(--f);font-size:13.5px;font-weight:600;
  cursor:pointer;width:100%;flex-shrink:0}
.ck-go:hover{background:var(--acBg)}
.ck-go:disabled{opacity:.6;cursor:default}

/* == 54. An agenda row ====================================================
   A meeting as a tinted block: time, subject, and one control or state.
   No rail (§4). The next meeting carries ONE marker: the "Next" pill, or,
   when it has a Join button instead, a 1px accent ring. */
.ag{display:flex;gap:12px;align-items:stretch;border-radius:var(--rl);
  padding:10px 12px;flex-shrink:0;background:var(--bgI);min-width:0}
.ag-t{width:62px;font-size:12px;font-weight:600;color:var(--tx3);
  padding-top:2px;flex-shrink:0;font-variant-numeric:tabular-nums}
.ag-b{flex:1;min-width:0}
.ag-n{font-size:13.5px;font-weight:600;overflow-wrap:anywhere}
.ag-s{font-size:12px;color:var(--tx3);font-weight:500;margin-top:1px;
  overflow-wrap:anywhere}
.ag-x{align-self:center;flex:none}
/* One ground for every row; the ring only where no pill says "Next". */
.ag.now:has(> a.ag-x){box-shadow:inset 0 0 0 1px var(--ac)}
.ag.done .ag-n{color:var(--tx3)}
.ag.free{background:none;box-shadow:inset 0 0 0 1px var(--bd)}
.ag.free .ag-n{color:var(--tx3)}

/* == 55. A task with a box beside it (.tkq — .tk is the support desk's) ======================================
   Things this person has to do. The square is a marker rather than a control
   — it is not a checkbox, because nothing here is completed by ticking it;
   every row is a link to the screen where the work happens. Drawn as a square
   because a column of them reads as a list of outstanding items, which is
   exactly what it is. */
.tkq{display:flex;gap:10px;align-items:flex-start;flex-shrink:0;min-width:0;
  color:var(--tx)}
a.tkq:hover{text-decoration:none}
a.tkq:hover .tkq-n{color:var(--ac)}
.tkq-box{width:17px;height:17px;border-radius:6px;border:1.8px solid var(--bd);
  margin-top:1px;flex-shrink:0}
.tkq-b{flex:1;min-width:0}
/* display:block, or the title and its sentence render as one run-on
   line — the trap section 4 of CLAUDE.md has now caught six times. */
.tkq-n{display:block;font-size:13.5px;font-weight:600;overflow-wrap:anywhere}
.tkq-s{display:block;font-size:12px;color:var(--tx3);font-weight:500;margin-top:1px}
.tkq-w{flex:none;white-space:nowrap}
/* The divider and the heading over the second list. Two lists that look alike
   and mean opposite things — mine to do, theirs to decide — so the heading
   between them is doing real work. */
.tkq-sep{height:1px;background:var(--bd);margin:13px 0 11px;flex-shrink:0}
.tkq-cap{font-size:12px;font-weight:500;letter-spacing:0;
  color:var(--tx3);margin-bottom:9px;flex-shrink:0}

/* == 56. A bar per weekday ================================================
   The week as seven columns. The bar grows from the floor of a fixed track
   rather than the column being the bar, so the labels line up whatever the
   hours are. A day with no hours draws a 5 px stub, not a nought: nought
   reads as "I worked zero" and a stub reads as "not yet", and on a Wednesday
   that is the whole difference. */
.wkg{flex:1;display:flex;align-items:flex-end;gap:12px;padding:8px 4px 0;
  min-height:0}
.wkg-c{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;
  height:100%;justify-content:flex-end;min-width:0}
.wkg-v{font-size:11px;font-weight:600;color:var(--tx3);
  font-variant-numeric:tabular-nums}
.wkg-r{width:100%;max-width:42px;border-radius:8px;background:var(--g-gn);
  opacity:.55;min-height:5px}
.wkg-c.today .wkg-r{background:var(--g-am);opacity:1}
.wkg-c.today .wkg-v{color:var(--am);font-weight:600}
.wkg-c.off .wkg-r{background:var(--bd);opacity:1}
.wkg-d{display:flex;gap:12px;padding:6px 4px 0;flex-shrink:0}
.wkg-d > div{flex:1;text-align:center;font-size:11.5px;font-weight:600;
  color:var(--tx3);min-width:0}
.wkg-d > div.today{color:var(--am)}
.wkg-d > div.off{color:var(--bd)}

/* == 57. One figure in a tinted box =======================================
   The last payslip. Read from across a desk, which is the only reason
   anything in this product is allowed to be 22 px. */
.paybox{background:var(--gnBg);border-radius:12px;padding:12px 14px;
  flex-shrink:0}
.paybox .lb{font-size:12px;font-weight:500;color:var(--gn)}
.paybox .v{font-size:22px;font-weight:600;letter-spacing:var(--ls-n);margin-top:3px;
  font-variant-numeric:tabular-nums}
.paybox .s{font-size:11.5px;color:var(--tx3);font-weight:500;margin-top:2px}

/* == 58. A goal with a track ==============================================
   Used by the KRA card. The per-goal hue is positional, matching the stacked
   bar — nothing here means good or bad, so nothing here borrows a tone that
   does. */
.goal{flex-shrink:0}
.goal-h{display:flex;justify-content:space-between;gap:8px;font-size:13px;
  font-weight:600;margin-bottom:6px}
.goal-t{height:7px;border-radius:6px;background:var(--bg);overflow:hidden}
.goal-t i{display:block;height:100%;border-radius:6px;background:var(--g-gn)}
.goal.k1 .goal-t i{background:var(--g-am)} .goal.k1 .goal-h span:last-child{color:var(--am)}
.goal.k2 .goal-t i{background:var(--g-vi)} .goal.k2 .goal-h span:last-child{color:var(--vi)}
.goal.k3 .goal-t i{background:var(--g-bl)} .goal.k3 .goal-h span:last-child{color:var(--bl)}
.goal.k0 .goal-h span:last-child{color:var(--gn)}

/* == 59. A date as a tile =================================================
   A holiday. The month sits over the day so the tile stays 40 px wide
   whatever the length of the month name. */
.dtl{display:flex;align-items:center;gap:11px;flex-shrink:0;min-width:0}
.dtl-c{width:40px;height:40px;border-radius:10px;background:var(--bgI);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  flex-shrink:0}
.dtl-c .mo{font-size:9.5px;font-weight:600;color:var(--tx3)}
.dtl-c .dy{font-size:15px;font-weight:600;line-height:1}
.dtl.soon .dtl-c{background:var(--gnBg)}
.dtl.soon .dtl-c .mo{color:var(--gn)} .dtl.soon .dtl-c .dy{color:var(--acD)}
.dtl-b{flex:1;min-width:0}
.dtl-n{font-size:13px;font-weight:600;overflow-wrap:anywhere}
.dtl-s{font-size:11.5px;color:var(--tx3);font-weight:500}

/* == 60. A face beside a name =============================================
   Shared by the presence list, the celebrations card and the waiting-on-
   others list. */
.fc{width:32px;height:32px;border-radius:50%;flex:none;display:grid;
  place-items:center;font-size:11px;font-weight:600;overflow:hidden}
.fc.sm{width:28px;height:28px;font-size:10.5px}
img.fc{object-fit:cover}
.fstk{display:flex;flex-shrink:0}
.fstk > *{border:2px solid var(--bg2)}
.fstk > * + *{margin-left:-8px}
.fstk .more{background:var(--bgI);color:var(--tx2);font-size:10px}
.prw{display:flex;align-items:center;gap:9px;flex-shrink:0;min-width:0}
.prw .nm{flex:1;min-width:0;font-size:13px;font-weight:600;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.prw .st{font-size:11.5px;color:var(--tx3);font-weight:500;flex:none}
/* Three states and no animation: a pulsing dot on a screen somebody keeps
   open all day is movement in the corner of their eye for eight hours. */
.pdot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--g-gy)}
.pdot.in{background:var(--g-gn)} .pdot.rm{background:var(--g-bl)}
.pdot.off{background:var(--bd)}


/* == 61. A select you can type into =======================================
   The trigger, the filter and the list. The <select> itself is still in the
   DOM and still the value — it is moved out of sight rather than replaced, so
   every form, validator and script that reads it keeps working. `position:
   absolute` rather than `display:none`, because a hidden field is skipped by
   some browsers' form validation and this one still has to be validated. */
.slx{position:relative}
.slx-src{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;
  left:0;bottom:0;padding:0;border:0;margin:0}
.slx-btn{display:flex;align-items:center;gap:8px;width:100%;height:38px;
  padding:0 12px;border:1px solid var(--bd);border-radius:var(--rl);
  background:var(--bgI);font-family:var(--f);font-size:13px;font-weight:500;
  color:var(--tx);cursor:pointer;text-align:left}
.slx-btn:hover{border-color:var(--ac)}
.slx.on .slx-btn{border-color:var(--ac);box-shadow:var(--ring);background:var(--bg2)}
.slx-v{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.slx-v.ph{color:var(--tx3)}
.slx-btn .car{width:5px;height:5px;border-right:1.6px solid var(--tx3);
  border-bottom:1.6px solid var(--tx3);transform:translateY(-2px) rotate(45deg);
  flex:none}
.slx-pop{position:absolute;top:42px;left:0;right:0;z-index:320;display:none;
  background:var(--bg2);border:1px solid var(--bd);border-radius:var(--rl);
  box-shadow:var(--shL);overflow:hidden}
.slx.on .slx-pop{display:block}
.slx-f{display:flex;align-items:center;gap:8px;padding:9px 12px;
  border-bottom:1px solid var(--bdL);color:var(--tx3)}
.slx-f input{border:0;background:none;height:auto;padding:0;font-size:13px;
  font-weight:500;flex:1;min-width:0}
.slx-f input:focus{box-shadow:none;border:0;background:none}
/* This one keeps its scrollbar. A filter list is a menu somebody is
   actively hunting in, often much longer than the box, and the bar is the
   only thing saying how much more there is. */
.slx-l{max-height:244px;overflow-y:auto;padding:5px}
.slx-i{padding:8px 11px;border-radius:8px;font-size:13px;font-weight:500;
  cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* `.at` is where the keyboard is, `.on` is what is chosen. They are different
   facts and a list where they look the same is one you get lost in. */
.slx-i.at{background:var(--bg3)}
.slx-i.on{color:var(--acD);font-weight:600}
/* The mark is drawn, not typed: a tick character is a glyph, and the
   kit says a state with a line or with words. */
.slx-i.on::after{content:"";float:right;width:5px;height:9px;margin:4px 4px 0 0;
  border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:rotate(45deg);opacity:.7}
.slx-none{padding:14px 11px;font-size:12px;color:var(--tx3);text-align:center}

/* == 62. The phone, tightened =============================================
   Every screen already FITS a phone (measured, all sixty at 390 px). This
   block makes it feel like an app rather than a shrunk desk: the home deck
   goes compact, dialogs use the whole height, and the product switcher can
   never hang off the glass. */
@media(max-width:700px){
  /* A real gutter, at a specificity that wins. The ≤1023 block's
     `.side + .main{padding-left:0}` outranked a bare `.main` rule on
     every page with a rail — which is every page — so headings sat on
     the glass. Same compound selector, later in the file. */
  .side + .main,.main,.scr > .main{padding:16px 18px 34px}
  .deck{gap:9px}
  .deck > .dk{padding:13px 14px;border-radius:13px}
  .dk-t{font-size:11px}
  .ck-n{font-size:33px}
  .ck-t{margin:10px 0 2px}
  .kpi{padding:12px 13px}
  .ph{margin-bottom:10px}
  .ph h1{font-size:19px}
}
@media(max-width:560px){
  /* Air around the sheet: a dialog touching three edges reads bigger
     than it is. Fourteen a side plus a softer radius and the same form
     reads like a card, not a takeover. */
  .mm{padding:20px 14px}
  .md{max-height:calc(100dvh - 40px);border-radius:14px}
  .md-b{padding:12px 15px}
}

/* == 63. The phone, properly ==============================================
   Two decisions that make a phone feel like an app rather than a shrunk
   desk. The page renders at 85% — the "zoom out" that fits half again as
   much on one screen, with media queries still reading the true viewport —
   and the rail stops being a strip of chips eating the top of every page:
   it is an off-canvas drawer behind a burger in the strip, over everything
   (z 460), closed by its backdrop, by Escape, or by choosing a row. Pages
   with no rail never draw the burger — EF.mobileRail() checks first. */
.nav-burger{display:none;width:32px;height:32px;place-items:center;
  border:none;background:none;border-radius:9px;color:var(--tx2);
  cursor:pointer;flex:none;padding:0}
.nav-burger:active{background:var(--bg3)}
.nav-burger svg.i{width:19px;height:19px}
.rail-bk{position:fixed;inset:0;z-index:450;background:rgba(6,8,12,.42);
  display:none}
@media(max-width:700px){
  /* The width compensates the zoom exactly: Chrome sometimes lays the
     body out at the viewport width and THEN scales it, which left a dead
     15% strip down the right edge — the cards looked pushed off the
     glass. 100vw over the zoom factor renders back to precisely one
     screen wide, whichever layout the browser picked. */
  body{zoom:.8;min-width:calc(100vw / 0.8)}
  html{overflow-x:hidden}
  /* The drawer itself lives in the 1023 block now - tablets share it. */
}

/* == 64. The phone, final polish ==========================================
   Cards breathe at the edges, sit tighter inside, and a data table is one
   line per row that the thumb swipes sideways — never a squeezed column
   wrapping into a tall row, never a scroller inside the scroller. */
@media(max-width:700px){
  .cd{border-radius:12px;margin-bottom:12px}
  .cd-h{padding:11px 13px}
  .cd-bd{padding:12px 13px}
  .cd:not(:has(> .cd-h)):not(:has(> .cd-bd)){padding:12px 13px}
  /* One line per row, the row swipes. Cells stay single-line by the
     table's own nowrap; a rambling cell is capped and ellipsised so one
     long subject cannot make the swipe a kilometre. */
  .rtw{max-height:none;min-height:0}
  .dt th,.dt td{padding:8px 10px}
  /* The page header: title on its own line, actions full width under it. */
  .ph{flex-wrap:wrap;gap:8px}
  /* Chips rows and tab strips swipe in one line instead of stacking three
     deep. The scrollbar is hidden the deck-card way. */
  .tabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch}
  .tabs::-webkit-scrollbar{display:none}
  .tabs .tab{white-space:nowrap;flex:none}
  .fld input,.fld select,.fld textarea{font-size:13px}
  /* The switcher and the bell drop as sheets pinned to the glass — an
     absolute pop anchored to a button near the middle of the strip hung
     off the right edge and dragged the whole page sideways with it. The
     width mirrors the body's own zoom compensation, which is the one
     formula proven to render exactly one screen wide. */
  .sw-pop,.bell-pop{position:fixed;left:10px;top:62px;
    width:calc(100vw / 0.8 - 20px);max-width:none;
    max-height:calc(100dvh / 0.8 - 90px);overflow:auto}
  .sw-pop .kbd{display:none}
  body{overflow-x:clip}
  /* Dialog forms at phone scale: shorter fields, quieter labels, tighter
     rows — a five-field form fits one sheet instead of two screens of
     scrolling. Validation dialogs are the same .md shell, so they follow. */
  .md .fld input,.md .fld select,.md input[type=date],.md input[type=time],
  .md input[type=number],.md input[type=text],.md select{
    height:32px;font-size:12px;padding:0 10px}
  .md .fld textarea,.md textarea{font-size:12px;padding:7px 10px;
    min-height:50px}
  .md .fld label{font-size:8.5px;margin-bottom:3px}
  .md .fld{margin-bottom:8px}
  .md .check{padding:8px 11px}
  .md .check-title{font-size:11.5px}
  .md .check-sub{font-size:9.5px;margin-top:2px}
  .md .hint{font-size:9.5px;margin-top:4px}
  .md .banner,.md .bn{padding:9px 11px;font-size:11px}
  .md .ig .pfx{height:34px}
  .md-h{padding:10px 13px}
  .md-t{font-size:13.5px}
  .md-s{font-size:9px}
  .md-f{padding:9px 13px}
  .md-f .btn{height:32px;font-size:12px}
  .fld{margin-bottom:10px}
  .md-f{padding-top:10px;padding-bottom:10px}
  /* The strip breathes like an app bar, not a desktop header. */
  .nav-in{height:50px;padding:0 12px}
  /* The greeting: a phone headline, not a poster. */
  .hail-h{font-size:19px}
  .hail-s{font-size:11px;line-height:1.6}
  .hail{gap:10px;margin-bottom:4px}
}

/* == 39. Masked money ======================================================
   A figure drawn as ###### until the employee code confirms the viewer
   means to look, then thirty seconds of the truth. A button so it is
   keyboard-reachable; monospace so the mask and the money hold one width. */
.mskv{font-family:'JetBrains Mono',monospace;font-size:inherit;
  font-weight:600;color:var(--tx2);background:var(--bgI);
  border:1px solid var(--bd);border-radius:6px;padding:2px 8px;
  cursor:pointer;letter-spacing:1px;line-height:1.5}
.mskv:hover{border-color:var(--ac);color:var(--tx)}
.mskv.on{color:var(--tx);background:var(--acBg);border-color:var(--ac);
  letter-spacing:0}

/* == 40. The status stepper, as EF.stepper draws it =========================
   `.stp` above is the wizard's strip. EF.stepper uses it for a record's
   lifecycle too, with the chain's meanings merged in: `.dn` done, `.on`
   waiting here, `.rj` turned down here, `.hold` held here. `.stp-w` lets
   a long lifecycle wrap rather than scroll with its scrollbar hidden,
   which on a phone was a strip whose last four steps nobody knew about.
   The label and its note are two stacked spans, so both are blocks. */
.stp-w{flex-wrap:wrap;row-gap:10px;overflow:visible;margin-bottom:0;
  padding-bottom:0}
.stp-t{display:flex;flex-direction:column;min-width:0}
.stp-t .stp-l{display:block}
.stp-s{display:block;font-size:9.5px;font-weight:500;color:var(--tx3);
  white-space:nowrap;margin-top:1px}
.stp-n svg.i{width:12px;height:12px}
.stp-i.rj .stp-n{background:var(--rd);color:#fff;border-color:var(--rd)}
.stp-i.rj .stp-l,.stp-i.rj .stp-s{color:var(--rd)}
.stp-i.hold .stp-n{background:var(--am);color:#fff;border-color:var(--am)}
.stp-i.hold .stp-l,.stp-i.hold .stp-s{color:var(--am)}
.stp-i.on .stp-s{color:var(--tx2)}
@media(max-width:700px){
  .stp-w .stp-bar{width:14px;margin:0 6px}
  .stp-w .stp-s{white-space:normal}
}

/* == 41. One notice ==========================================================
   EF.notice. A wash and a tinted icon carry the tone; no rail, no fill on
   the words. The body wraps anywhere because it often holds a code or an
   account number, and an unbroken token must not widen a phone page. */
.ntc{display:flex;align-items:flex-start;gap:11px;padding:11px 14px;
  border:1px solid var(--bd);border-radius:var(--rl);background:var(--bg2);
  margin-bottom:11px}
.ntc-ic{flex:none;display:grid;place-items:center;width:20px;height:20px;
  color:var(--tx3)}
.ntc-ic svg.i{width:15px;height:15px}
.ntc-b{flex:1;min-width:0}
.ntc-t{font-size:12.5px;font-weight:600;letter-spacing:0;color:var(--tx)}
.ntc-x{font-size:11.5px;color:var(--tx2);margin-top:3px;line-height:1.55;
  overflow-wrap:anywhere}
.ntc > .btn{flex:none;align-self:center}
.ntc-i{background:color-mix(in srgb,var(--blBg) 60%,var(--bg2))}
.ntc-i .ntc-ic{color:var(--bl)}
.ntc-w{background:var(--amBg);border-color:color-mix(in srgb,var(--am) 24%,var(--bd))}
.ntc-w .ntc-ic{color:var(--am)}
.ntc-r{background:var(--rdBg);border-color:color-mix(in srgb,var(--rd) 40%,var(--bd))}
.ntc-r .ntc-ic,.ntc-r .ntc-t{color:var(--rd)}
.ntc-o{background:var(--gnBg);border-color:color-mix(in srgb,var(--gn) 24%,var(--bd))}
.ntc-o .ntc-ic{color:var(--gn)}
@media(max-width:560px){
  .ntc{flex-wrap:wrap}
  .ntc > .btn{margin-left:31px}
}

/* == 42. The overflow menu ===================================================
   EF.more. Fixed to the glass and appended to the body, like the column
   filter, so no card's overflow can clip it. */
.more-p{position:fixed;z-index:520;background:var(--bg2);min-width:200px;
  max-width:min(300px,calc(100vw - 16px));max-height:min(420px,calc(100vh - 24px));
  overflow:auto;border:1px solid var(--bd);border-radius:10px;
  box-shadow:var(--shL);padding:5px;animation:pop .14s ease-out}
.more-i{display:flex;align-items:center;gap:9px;width:100%;padding:7px 9px;
  border:0;border-radius:7px;background:none;font-family:var(--f);
  font-size:11.5px;font-weight:500;color:var(--tx);text-align:left;
  cursor:pointer;min-width:0}
.more-i > .lb{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.more-i > .rt{flex:none;font-size:9px;color:var(--tx3);font-weight:600}
.more-i svg.i{width:14px;height:14px;flex:none;color:var(--tx3)}
.more-i:hover,.more-i:focus-visible{background:var(--bg3);text-decoration:none;
  outline:none}
.more-i.dg,.more-i.dg svg.i{color:var(--rd)}
.more-sep{height:1px;background:var(--bdL);margin:4px 2px}

/* == 43. The wizard ==========================================================
   EF.wizard: the stepper, the step, and one line for a refusal. */
.wzd-s{margin-bottom:14px}
.wzd-s:empty{display:none}
.wzd-b{min-width:0}
.wzd-e{margin-top:10px}

/* == 44. Choosing several rows ===============================================
   EF.table's tick column and the bar that stays on screen while anything
   is ticked. The bar sticks to the bottom of whatever scrolls the page, so
   the actions are in reach from the fortieth row. */
table.dt th.tbl-ck,table.dt td.tbl-ck{width:34px;min-width:34px;
  max-width:34px;text-align:center;padding-left:0;padding-right:0}
table.dt th.tbl-ck .th-in{justify-content:center;padding-left:0;padding-right:0}
table.dt td.tbl-ck{cursor:default}
.tbl-bulk{position:sticky;bottom:0;z-index:6;display:flex;align-items:center;
  gap:6px;flex-wrap:wrap;padding:8px 12px;background:var(--acBg);
  border-top:1px solid color-mix(in srgb,var(--ac) 30%,var(--bd));
  box-shadow:0 -6px 16px rgba(22,38,31,.06)}
.tbl-bulk-n{font-size:11.5px;font-weight:600;color:var(--tx);margin-right:4px;
  white-space:nowrap}
.tbl-bulk .gap{flex:1}
@media(max-width:700px){
  .tbl-bulk{padding:8px 10px}
  .tbl-bulk .gap{display:none}
}

/* == 45. The installable app =================================================
   The My space card, the iPhone instructions, and the two profile rows.
   `.pf-mob` is a menu row for the phone only - the Mail row, whose icon is
   in the strip on a desk. `.pf-x` is a row that states a fact and goes
   nowhere, so it does not light up under the pointer. */
.app-ins{display:flex;align-items:center;gap:12px;padding:12px 14px;
  margin-bottom:11px;border:1px solid color-mix(in srgb,var(--ac) 22%,var(--bd));
  border-radius:var(--rl);background:var(--acBg)}
.app-ins-ic{flex:none;width:34px;height:34px;border-radius:10px;
  display:grid;place-items:center;background:var(--bg2);color:var(--acD)}
.app-ins-ic svg.i{width:17px;height:17px}
.app-ins-b{flex:1;min-width:0}
.app-ins-t{display:block;font-size:12.5px;font-weight:600;color:var(--tx)}
.app-ins-s{display:block;font-size:11px;color:var(--tx2);margin-top:2px;
  line-height:1.5}
.app-ins-a{display:flex;gap:6px;flex-wrap:wrap;flex:none}
.app-ins .bn-x-btn{align-self:flex-start}
@media(max-width:700px){
  .app-ins{flex-wrap:wrap;align-items:flex-start}
  .app-ins-b{flex-basis:calc(100% - 90px)}
  .app-ins-a{flex-basis:100%;order:3}
}
.app-steps{margin:0;padding-left:18px;font-size:12px;line-height:1.7;
  color:var(--tx2)}
.app-steps li{margin-bottom:6px}
.app-steps b{font-weight:600;color:var(--tx)}
.app-steps-i{display:inline-grid;place-items:center;vertical-align:-3px;
  width:18px;height:18px;border-radius:5px;background:var(--bg3);color:var(--bl)}
.app-steps-i svg.i{width:12px;height:12px}
.pf-i.pf-x{cursor:default}
.pf-i.pf-x:hover{background:none}
.pf-i.pf-mob{display:none}
/* The mail count wears blue, not the bell's red: unread mail is news, not
   something overdue. */
#efMail .nav-ico .dot{background:var(--rd)}
@media(max-width:700px){
  #efMail{display:none}
  .pf-i.pf-mob{display:flex}
}

/* The burger, said last: its base display:none sits below the 1023 block
   in this file, so the media rule that shows it has to come later still. */
@media(max-width:1023px){
  .nav-burger{display:grid}
}

/* == EVA, the assistant ======================================================
   A floating button and a docked panel, drawn by eva.js only for somebody
   the server says may use EVA. The panel sits above the page and above an
   open dialog's backdrop, so "fill this form" can be said while the form is
   open. Below 700px the panel is the whole screen.

   EVA wears its own small palette, taken from its logo - a deep ink, a
   blue and a cyan - so it reads as one product inside any company's
   colours. It is scoped to EVA's own chrome: the controls EVA puts on a
   company's screen that belong to the company (Confirm, Save, Open) keep
   the company's accent.

   EVA is also the one deliberate exception to "nothing animated": a
   streaming answer pulses its status line, turns a small ring while a
   lookup runs, lets new cards rise in, and lights each field it fills.
   All of it is short, quiet and flat - one colour at a time, no gradient
   and no glow anywhere but the voice stage - and all of it stops under
   prefers-reduced-motion. Nothing blinks. */
:root{
  --ev-ink:#0E1422; --ev-ink2:#1A2335; --ev-bl:#2358E8; --ev-cy:#14B4EC;
  --ev-bg:#F6F8FD; --ev-tint:#EAF0FE; --ev-bd:#DCE4F4; --ev-bdL:#EDF1F8;
  --ev-tx:#101828; --ev-tx2:#3F4A5C; --ev-tx3:#5B6577;
  --ev-amBg:#FFF6E6; --ev-amBd:#E3A94F;
  --ev-sh:0 24px 60px rgba(14,20,34,.22),0 2px 8px rgba(14,20,34,.08);
  --ev-ring:0 0 0 3px rgba(35,88,232,.14);
}
.ev-logo{display:block;flex:none;object-fit:contain;user-select:none}
.ev-logo-i{display:grid;place-items:center;border-radius:28%;background:var(--ev-bl);color:#fff}
.ev-logo-i .i{width:62%;height:62%}

/* The button */
.ev-fab{position:fixed;right:18px;bottom:18px;z-index:290;display:inline-flex;
  align-items:center;gap:9px;height:44px;padding:0 17px 0 7px;border-radius:var(--rp);
  border:1px solid rgba(255,255,255,.1);background:var(--ev-ink);color:#fff;
  font:600 12.5px var(--f);letter-spacing:.1px;cursor:pointer;
  box-shadow:0 10px 26px rgba(14,20,34,.26),0 1px 3px rgba(14,20,34,.18);
  transition:transform .2s ease,box-shadow .15s ease,opacity .15s ease}
.ev-fab:hover{background:var(--ev-ink2);box-shadow:0 12px 30px rgba(14,20,34,.32)}
.ev-fab:focus-visible{outline:2px solid var(--ev-bl);outline-offset:2px}
.ev-fab .ev-fabl{width:30px;height:30px}
.ev-fab.on{opacity:0;pointer-events:none}
.ev-has .scr{padding-bottom:72px}

/* The panel */
.ev-dock{position:fixed;right:18px;bottom:18px;z-index:330;width:min(440px,calc(100vw - 36px));
  height:min(700px,calc(100vh - 36px));display:flex;flex-direction:column;
  background:#fff;color:var(--ev-tx);font-family:var(--f);
  border:1px solid var(--ev-bd);border-radius:18px;box-shadow:var(--ev-sh);overflow:hidden;
  animation:evin .2s cubic-bezier(.2,.8,.3,1);contain:strict}
/* `contain:strict` makes the panel its own layout island: a streamed word
   re-lays out the panel and never the page under it, and the page being
   filled never re-lays out the panel. Its size never came from its
   contents - it is set above, and on a phone by its four edges. */
.ev-dock[hidden]{display:none}
.ev-dock.ev-wide{width:min(780px,calc(100vw - 36px));height:calc(100vh - 36px)}
@keyframes evin{from{opacity:0;transform:translateY(10px) scale(.985)}}
.ev-hd{display:flex;align-items:center;gap:10px;padding:11px 10px 11px 14px;
  border-bottom:1px solid var(--ev-bdL);background:#fff}
.ev-hlg{width:32px;height:32px}
.ev-hx{min-width:0}
.ev-nm{font-weight:600;font-size:14.5px;letter-spacing:.2px;color:var(--ev-ink);line-height:1.2}
.ev-sb{font-size:10.5px;font-weight:500;color:var(--ev-tx3);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.ev-sp{flex:1;min-width:4px}
.ev-ib{width:30px;height:30px;border-radius:9px;border:0;background:transparent;
  color:var(--ev-tx2);display:grid;place-items:center;cursor:pointer;flex:none;padding:0}
.ev-ib:hover{background:var(--ev-tint);color:var(--ev-ink)}
.ev-ib:focus-visible{outline:2px solid var(--ev-bl);outline-offset:1px}
.ev-ib .i{width:16px;height:16px}
.ev-ib[aria-pressed="true"]{color:var(--ev-bl)}
/* The drawn mark on a tile, as the control plane's screens use it; a logo
   image inside the tile stands on its own. */
.ev-mk{width:32px;height:32px;border-radius:10px;display:grid;place-items:center;
  background:var(--ev-bl);color:#fff;flex:none;overflow:hidden}
.ev-mk .i{width:18px;height:18px}
.ev-mk:has(> img){background:none}
.ev-mk img{width:100%;height:100%;object-fit:contain}

.ev-bd{flex:1;overflow-y:auto;padding:16px 16px 10px;display:flex;flex-direction:column;
  gap:16px;background:var(--ev-bg);overscroll-behavior:contain}
.ev-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}

/* The welcome */
.ev-wel{margin:auto 0;padding:6px 4px 2px;display:flex;flex-direction:column;align-items:flex-start}
.ev-wlg{width:56px;height:56px;margin-bottom:14px}
.ev-wt{font-size:18px;font-weight:600;color:var(--ev-ink);letter-spacing:-.012em;margin-bottom:6px}
.ev-ws{font-size:12.5px;color:var(--ev-tx2);line-height:1.6;max-width:46ch}
.ev-sg{display:flex;flex-direction:column;gap:6px;margin-top:18px;width:100%}
.ev-chip{display:flex;align-items:center;gap:9px;width:100%;border:1px solid var(--ev-bd);
  background:#fff;color:var(--ev-ink2);border-radius:12px;padding:9px 12px;
  font:500 12px/1.4 var(--f);cursor:pointer;text-align:left;
  transition:border-color .12s,background .12s}
.ev-chip:hover{border-color:var(--ev-bl);background:var(--ev-tint)}
.ev-chip:focus-visible{outline:2px solid var(--ev-bl);outline-offset:1px}
.ev-chip .i{width:14px;height:14px;color:var(--ev-bl);flex:none}

/* A conversation */
.ev-m{display:flex;gap:10px;align-items:flex-start;max-width:100%}
.ev-us{justify-content:flex-end}
.ev-us .ev-bx{background:var(--ev-ink2);color:#fff;border-radius:16px 16px 4px 16px;
  padding:9px 13px;font-size:12.5px;line-height:1.55;max-width:85%;overflow-wrap:anywhere;
  box-shadow:0 1px 2px rgba(14,20,34,.14)}
.ev-av{flex:none;margin-top:1px}
.ev-av .ev-logo{width:24px;height:24px}
.ev-as .ev-bx{min-width:0;flex:1;font-size:12.8px;line-height:1.62;color:var(--ev-tx);
  overflow-wrap:anywhere}
.ev-ans:empty{display:none}
.ev-bx p{margin:0 0 8px}
.ev-bx p:last-child{margin-bottom:0}
.ev-bx ul,.ev-bx ol{margin:4px 0 8px;padding-left:18px}
.ev-bx li{margin:2px 0}
.ev-bx b{font-weight:600}
.ev-bx code{font:11.5px var(--fm);background:var(--ev-tint);color:var(--ev-ink);padding:1px 5px;
  border-radius:5px}
.ev-pre{font:11.5px/1.5 var(--fm);background:var(--ev-ink);color:#E6ECF8;border-radius:10px;
  padding:10px 12px;margin:6px 0 8px;overflow-x:auto;white-space:pre}
.ev-h4{font-weight:600;color:var(--ev-ink);margin:8px 0 4px}
.ev-tw{overflow-x:auto;margin:6px 0 8px;border:1px solid var(--ev-bd);border-radius:10px;background:#fff}
.ev-t{border-collapse:collapse;font-size:11.5px;width:100%}
.ev-t th,.ev-t td{text-align:left;padding:6px 9px;border-bottom:1px solid var(--ev-bdL);white-space:nowrap}
.ev-t tr:last-child td{border-bottom:0}
.ev-t th{font-weight:600;color:var(--ev-tx3);background:#F8FAFE;font-size:10.5px}
.ev-caret{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--ev-bl);
  margin-left:5px;vertical-align:middle;opacity:.7}
.ev-err{color:var(--rd);font-size:12px;margin-top:6px}
.ev-note{color:var(--ev-tx3);font-size:11.5px;margin-top:6px}
.ev-mu{color:var(--ev-tx3)}

/* The status line and the timeline of lookups */
.ev-stat{font-size:12px;font-weight:500;color:var(--ev-tx3);padding:1px 0 3px}
.ev-shim{color:var(--ev-tx3);animation:evpulse 1.6s ease-in-out infinite}
@keyframes evpulse{50%{opacity:.45}}
.ev-run{margin:0 0 9px;border:1px solid var(--ev-bd);background:#fff;border-radius:12px;overflow:hidden}
.ev-rh{display:flex;align-items:center;gap:8px;width:100%;border:0;background:none;
  padding:8px 11px;font:500 11.5px var(--f);color:var(--ev-tx2);cursor:default;text-align:left}
.ev-done .ev-rh{cursor:pointer}
.ev-done .ev-rh:hover{background:#F8FAFE}
.ev-rh:focus-visible{outline:2px solid var(--ev-bl);outline-offset:-2px}
.ev-rhi{width:16px;height:16px;display:grid;place-items:center;flex:none;color:var(--ev-bl)}
.ev-rhi .i{width:14px;height:14px}
.ev-chv{display:none;color:var(--ev-tx3)}
.ev-done .ev-chv{display:grid}
.ev-chv .i{width:14px;height:14px;transition:transform .15s}
.ev-shut .ev-chv .i{transform:rotate(-90deg)}
.ev-sts{list-style:none;margin:0;padding:0 11px 9px;display:flex;flex-direction:column;gap:6px}
.ev-shut .ev-sts{display:none}
.ev-st{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ev-tx2);min-width:0}
.ev-st-i{width:16px;height:16px;flex:none;display:grid;place-items:center}
.ev-st-i .i{width:13px;height:13px}
.ev-st-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ev-st-ms{font-size:10.5px;color:var(--ev-tx3);font-variant-numeric:tabular-nums;flex:none}
.ev-st.ok .ev-st-i{color:var(--ev-bl)}
.ev-st.err .ev-st-i,.ev-st.stop .ev-st-i{color:var(--ev-tx3)}
.ev-st.err .ev-st-l,.ev-st.stop .ev-st-l{color:var(--ev-tx3)}
.ev-st.say{align-items:flex-start;color:var(--ev-tx2)}
.ev-st.say .ev-st-l{white-space:normal;line-height:1.5}
.ev-st.say.fin .ev-st-l{color:var(--ev-ink);font-weight:600}
.ev-dot{display:block;width:5px;height:5px;border-radius:50%;background:var(--ev-bd);margin-top:6px}
.ev-spin{display:block;width:12px;height:12px;border-radius:50%;border:1.6px solid var(--ev-bd);
  border-top-color:var(--ev-bl);animation:evspin .7s linear infinite}
@keyframes evspin{to{transform:rotate(360deg)}}
.ev-plan .ev-run{margin-bottom:4px}
.ev-rise{animation:evrise .32s cubic-bezier(.2,.8,.3,1)}
@keyframes evrise{from{opacity:0;transform:translateY(6px)}}
.ev-skel{display:flex;flex-direction:column;gap:9px;padding:8px 0}
.ev-skel i{display:block;height:10px;border-radius:5px;background:#E6ECF8;
  animation:evpulse 1.4s ease-in-out infinite}

/* Under an answer */
.ev-tl{display:flex;flex-wrap:wrap;gap:2px;margin-top:6px}
.ev-tb{display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 8px;border:0;
  border-radius:8px;background:none;color:var(--ev-tx3);font:500 11px var(--f);cursor:pointer}
.ev-tb:hover{background:var(--ev-tint);color:var(--ev-ink)}
.ev-tb:focus-visible{outline:2px solid var(--ev-bl);outline-offset:1px}
.ev-tb:disabled{opacity:.6;cursor:default}
.ev-tb .i{width:13px;height:13px}

/* Cards: a chart, a page, a fill, a change */
.ev-card{margin-top:10px;border:1px solid var(--ev-bd);border-radius:14px;background:#fff;
  padding:12px 13px;box-shadow:0 1px 2px rgba(14,20,34,.04)}
.ev-ct{font-size:11.5px;font-weight:600;color:var(--ev-ink);margin-bottom:8px}
.ev-cs{width:100%;max-width:520px;height:auto;display:block}
.ev-gl{stroke:var(--ev-bdL);stroke-width:1}
.ev-ax{font:8px var(--f);fill:var(--ev-tx3)}
.ev-lg{display:flex;flex-wrap:wrap;gap:10px;font-size:10.5px;color:var(--ev-tx3);margin-top:6px}
.ev-lg i,.ev-dl i{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px;flex:none}
.ev-dn{display:flex;gap:12px;align-items:center}
.ev-dn svg{width:112px;height:112px;flex:none}
.ev-dl{display:flex;flex-direction:column;gap:4px;font-size:11px;min-width:0;flex:1}
.ev-dl div{display:flex;gap:6px;align-items:center}
.ev-dl span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ev-tx2)}
.ev-dl b{font-weight:600}
.ev-hb{display:flex;flex-direction:column;gap:5px}
.ev-hr{display:grid;grid-template-columns:minmax(0,34%) minmax(0,1fr) auto;gap:8px;align-items:center;font-size:11px}
.ev-hl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ev-tx2)}
.ev-hbar{height:8px;background:var(--ev-tint);border-radius:4px;overflow:hidden}
.ev-hbar i{display:block;height:100%;border-radius:4px}
.ev-hr b{font-weight:600;font-size:10.5px}
.ev-lrow{display:flex;align-items:center;gap:10px}
.ev-li{width:30px;height:30px;border-radius:9px;background:var(--ev-tint);color:var(--ev-bl);
  display:grid;place-items:center;flex:none}
.ev-li .i{width:15px;height:15px}
.ev-lx{flex:1;min-width:0;display:flex;flex-direction:column}
.ev-lt{display:block;font-weight:600;font-size:12.5px;color:var(--ev-ink);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.ev-ls{display:block;font-size:11px;color:var(--ev-tx3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ev-beat{margin-top:10px;padding-top:9px;border-top:1px solid var(--ev-bdL)}
.ev-bt{display:flex;align-items:center;gap:8px;font-size:11.5px;font-weight:500;color:var(--ev-tx3);min-height:26px}
.ev-bar{height:3px;border-radius:2px;background:var(--ev-tint);overflow:hidden;margin-top:6px}
.ev-bar i{display:block;height:100%;width:0;background:var(--ev-bl);border-radius:2px;
  animation:evbar 1.15s linear forwards}
@keyframes evbar{to{width:100%}}
.ev-fillc{display:flex;flex-wrap:wrap;gap:8px;align-items:center;background:#F4F8FF}
.ev-fci{width:22px;height:22px;border-radius:7px;background:var(--ev-tint);color:var(--ev-bl);
  display:grid;place-items:center;flex:none}
.ev-fci .i{width:13px;height:13px}
.ev-fct{flex:1;min-width:0;font-size:12px;color:var(--ev-tx2)}
.ev-at{display:flex;gap:9px;align-items:flex-start;font-weight:600;font-size:12.5px;color:var(--ev-ink);line-height:1.45}
.ev-ati{width:24px;height:24px;border-radius:8px;background:var(--ev-tint);color:var(--ev-bl);
  display:grid;place-items:center;flex:none;margin-top:-1px}
.ev-ati .i{width:13px;height:13px}
.ev-risk .ev-ati{background:var(--amBg);color:var(--am)}
.ev-an{font-size:11.5px;color:var(--ev-tx2);margin:6px 0 0 33px;line-height:1.5}
.ev-by{font-weight:600;color:var(--ev-ink)}
.ev-kv{display:grid;grid-template-columns:minmax(0,36%) minmax(0,1fr);gap:5px 12px;margin:10px 0 0;
  font-size:11.5px;padding:9px 10px;background:#F8FAFE;border-radius:10px}
.ev-kv dt{color:var(--ev-tx3)}
.ev-kv dd{margin:0;overflow-wrap:anywhere;color:var(--ev-tx);font-weight:500}
.ev-kv dd.ev-mu{color:var(--ev-tx3);font-weight:400}
.ev-ins{display:grid;grid-template-columns:minmax(0,1fr);gap:10px;margin-top:11px}
.ev-wide .ev-ins{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.ev-fi{min-width:0}
.ev-fi.ev-fw{grid-column:1/-1}
.ev-fi > label{display:block;font-size:10px;font-weight:600;color:var(--ev-tx3);margin-bottom:4px;
  letter-spacing:.2px}
.ev-fi .req{color:var(--rd);margin-left:2px}
.ev-fi input:not([type=checkbox]),.ev-fi select,.ev-fi textarea{height:34px;font-size:12.5px;
  border-radius:10px;padding:0 10px;background:#fff;border-color:var(--ev-bd)}
.ev-fi textarea{height:auto;min-height:58px;padding:8px 10px;line-height:1.5}
.ev-fi input:focus,.ev-fi select:focus,.ev-fi textarea:focus{border-color:var(--ev-bl);box-shadow:var(--ev-ring)}
.ev-fi.bad input:not([type=checkbox]),.ev-fi.bad select,.ev-fi.bad textarea{border-color:var(--rd);background:#FFFBFA}
.ev-fh{font-size:10px;color:var(--ev-tx3);margin-top:4px;line-height:1.45}
.ev-cbx{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--ev-tx);cursor:pointer}
.ev-cbx input{width:15px;height:15px;margin:0;accent-color:var(--ev-bl)}
.ev-warn{margin-top:9px;font-size:11px;color:var(--am);background:var(--amBg);border-radius:9px;padding:7px 9px}
.ev-cm{margin-top:9px;display:flex;gap:7px;align-items:flex-start;font-size:11.5px;line-height:1.45}
.ev-cm .i{width:14px;height:14px;flex:none;margin-top:1px}
.ev-ab{display:flex;justify-content:flex-end;gap:6px;margin-top:11px}
.ev-ar{margin-top:10px;font-size:11.5px;color:var(--ev-tx2);display:flex;flex-wrap:wrap;gap:6px 8px;align-items:center}
.ev-ar .i{width:14px;height:14px}
.ev-ok{color:var(--gn)}
.ev-no{color:var(--rd)}
.ev-wait{color:var(--am)}
.ev-yes{border-color:#CFE6DA}
.ev-past{box-shadow:none}

/* The box EVA is asked in */
.ev-in{padding:10px 12px 6px;background:#fff;border-top:1px solid var(--ev-bdL)}
.ev-box{display:flex;align-items:flex-end;gap:8px;border:1px solid var(--ev-bd);border-radius:14px;
  background:#fff;padding:5px 5px 5px 12px;transition:border-color .12s,box-shadow .12s}
.ev-box:focus-within{border-color:var(--ev-bl);box-shadow:var(--ev-ring)}
.ev-box textarea{flex:1;border:0;background:none;resize:none;padding:6px 0;height:auto;min-height:30px;
  max-height:140px;font:13px/1.5 var(--f);color:var(--ev-tx)}
.ev-box textarea:focus{outline:none;border:0;box-shadow:none;background:none}
.ev-go{width:32px;height:32px;border-radius:10px;border:0;background:var(--ev-ink);color:#fff;
  display:grid;place-items:center;cursor:pointer;flex:none;padding:0;transition:background .12s}
.ev-go:hover{background:var(--ev-bl)}
.ev-go:focus-visible{outline:2px solid var(--ev-bl);outline-offset:2px}
.ev-go .i{width:16px;height:16px;stroke-width:2.2}
.ev-go.ev-stop{background:var(--ev-tint);color:var(--ev-ink)}
.ev-go.ev-stop:hover{background:#DCE6FD}
.ev-go.ev-stop .i{fill:currentColor;stroke-width:1.4}
.ev-ft{font-size:10px;color:var(--ev-tx3);padding:0 14px 10px;background:#fff;text-align:center}

/* Earlier conversations */
.ev-hist{display:flex;flex-direction:column;gap:6px}
.ev-hhd{display:flex;align-items:center;gap:6px;margin-bottom:4px}
.ev-hh{font-weight:600;font-size:13px;color:var(--ev-ink)}
.ev-hr2{display:flex;gap:4px;align-items:center}
.ev-ht2{flex:1;min-width:0;text-align:left;border:1px solid var(--ev-bd);background:#fff;border-radius:11px;
  padding:9px 11px;cursor:pointer;display:flex;flex-direction:column;gap:2px;font:500 12px var(--f);color:var(--ev-tx)}
.ev-ht2:hover{border-color:var(--ev-bl)}
.ev-hr2.on .ev-ht2{border-color:var(--ev-bl);background:var(--ev-tint)}
.ev-ht2 span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ev-ht2 small{font-size:10.5px;color:var(--ev-tx3);font-weight:400}
.ev-empty{font-size:12px;color:var(--ev-tx3)}

/* Fill with EVA: beside the button that saves, and the box above it */
.ev-fillb{background:#fff;border-color:var(--ev-bd);color:var(--ev-ink2);gap:7px;padding:0 13px 0 8px}
.ev-fillb:hover{background:var(--ev-tint);border-color:var(--ev-bl);color:var(--ev-ink)}
.ev-fillb .ev-logo{width:20px;height:20px}
.ev-fillb.btn-sm .ev-logo{width:16px;height:16px}
.ev-fillb.btn-sm{padding:0 9px 0 6px;margin-right:6px}
.ev-fillbar{position:relative;border:1px solid var(--ev-bd);background:#fff;
  border-radius:14px;padding:10px 12px 12px;margin:14px 0 2px;overflow:hidden}
.ev-fl{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:600;color:var(--ev-ink);margin-bottom:8px}
.ev-fl .ev-logo{width:20px;height:20px}
.ev-fl .ev-ib{width:26px;height:26px}
.ev-fr{display:flex;gap:8px;align-items:flex-end}
.ev-fr textarea{flex:1;min-height:46px;height:auto;padding:8px 10px;font-size:12.5px;line-height:1.5;
  resize:vertical;border-radius:10px;background:#fff;border-color:var(--ev-bd)}
.ev-fr textarea:focus{border-color:var(--ev-bl);box-shadow:var(--ev-ring)}
.ev-fgo{background:var(--ev-ink);border-color:var(--ev-ink);color:#fff}
.ev-fgo:hover{background:var(--ev-bl);border-color:var(--ev-bl);color:#fff}
.ev-fm{margin-top:8px;font-size:11.5px;display:flex;flex-wrap:wrap;gap:6px 8px;align-items:center;color:var(--ev-tx2)}
.ev-fm > span{flex:1;min-width:0}
.ev-fm .i{width:14px;height:14px;flex:none}
.ev-fillbar.ev-busy::after{content:"";position:absolute;left:0;right:auto;top:0;height:2px;
  width:40%;background:var(--ev-bl);animation:evslide 1.1s ease-in-out infinite alternate}
/* Moved by transform, never by `left`: animating `left` lays the page
   out again on every frame for as long as a fill runs. 150% of a bar
   40% wide is the same 60% of travel. */
@keyframes evslide{from{transform:none}to{transform:translateX(150%)}}
/* A field EVA just filled lights for a moment; one it was not sure about
   stays amber, with a line under it, until somebody touches it. */
.ev-filled{border-color:var(--ev-bl) !important;box-shadow:0 0 0 3px rgba(35,88,232,.16) !important;
  animation:evfill 1.1s ease-out}
@keyframes evfill{0%{background-color:#DCE6FD;box-shadow:0 0 0 0 rgba(35,88,232,.45)}
  100%{box-shadow:0 0 0 3px rgba(35,88,232,.16)}}
.ev-unsure{border-color:var(--ev-amBd) !important;background-color:var(--ev-amBg) !important}
.ev-uh{font-size:10px;font-weight:500;color:var(--am);margin-top:5px}
/* Something EVA pointed at, or is about to press. */
.ev-ring{outline:2px solid var(--ev-bl) !important;outline-offset:2px;border-radius:6px;
  animation:evring 2.6s ease-out forwards}
tr.ev-ring > td{background:#EEF3FF !important}
@keyframes evring{0%{box-shadow:0 0 0 0 rgba(35,88,232,.4)}30%{box-shadow:0 0 0 7px rgba(35,88,232,.12)}
  100%{box-shadow:0 0 0 0 rgba(35,88,232,0)}}

@media (prefers-reduced-motion:reduce){
  .ev-dock,.ev-rise,.ev-spin,.ev-filled,.ev-ring,.ev-skel i,.ev-shim,
  .ev-fillbar.ev-busy::after{animation:none !important}
  .ev-bar i{animation:none;width:100%}
  .ev-fab,.ev-box,.ev-chv .i{transition:none}
}
@media (max-width:700px){
  .ev-fab{right:14px;bottom:calc(14px + env(safe-area-inset-bottom));height:50px;width:50px;
    padding:0;justify-content:center}
  .ev-fab-t{display:none}
  .ev-fab .ev-fabl{width:36px;height:36px}
  .ev-dock,.ev-dock.ev-wide{right:0;bottom:0;left:0;top:0;width:auto;height:auto;border-radius:0;
    border:0;animation:none}
  .ev-hd{padding-top:calc(11px + env(safe-area-inset-top));
    padding-left:calc(14px + env(safe-area-inset-left));padding-right:calc(10px + env(safe-area-inset-right))}
  .ev-ft{padding-bottom:calc(10px + env(safe-area-inset-bottom))}
  .ev-wd{display:none}
  .ev-as .ev-bx,.ev-us .ev-bx{font-size:14px}
  .ev-box textarea{font-size:15px}
  body.ev-opened{overflow:hidden}
  .ev-fillb span{display:none}
  .ev-fillb{padding:0 9px}
}
@media print{.ev-fab,.ev-dock,.ev-fillb,.ev-fillbar{display:none !important}}

/* The control plane's EVA editor: a switch, then four short sections. */
.ev-ed{display:flex;flex-direction:column;gap:4px}
.ev-edh{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--ev-bd);
  border-radius:14px;background:#fff;margin-bottom:6px}
.ev-edl{width:36px;height:36px}
.ev-edx{flex:1;min-width:0}
.ev-edt{font-weight:600;font-size:14px;color:var(--ev-ink)}
.ev-eds{font-size:11px;color:var(--ev-tx3);margin-top:1px}
.ev-sec{padding:12px 0 2px;border-top:1px solid var(--bdL)}
.ev-sech{font-size:12px;font-weight:600;color:var(--ev-ink);
  margin-bottom:10px}
.ev-sec .fld{margin-bottom:10px}
.ev-gm{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.7fr) minmax(0,.8fr);gap:0 12px}
.ev-mp{font-size:11px;color:var(--ev-tx3);margin:-4px 0 8px}
.ev-mp:empty{display:none}
.ev-capg{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px;margin-bottom:10px}
.ev-ck{display:flex;gap:8px;align-items:center;padding:7px 10px;border:1px solid var(--bd);border-radius:10px;
  cursor:pointer;font-size:12px;font-weight:500;color:var(--tx);background:var(--bg2)}
.ev-ck:hover{border-color:var(--ev-bl)}
.ev-ck:has(input:checked){border-color:var(--ev-bl);background:var(--ev-tint)}
.ev-ck input{width:15px;height:15px;margin:0;flex:none;accent-color:var(--ev-bl)}
.ev-g4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0 12px}
.ev-when{border-top:1px dashed var(--bdL);padding-top:10px;margin-top:2px;display:flex;flex-direction:column;gap:8px}
.ev-when .hint{margin-top:0}
.ev-chg{align-self:flex-start}
@media (max-width:700px){
  .ev-g4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ev-gm{grid-template-columns:minmax(0,1fr)}
}
