/* ============================================================
   Deskgrid — app-specific components.
   Loaded after app.css. Tokens only: no new colours, no gradients,
   no blur, no glow.
   0 accent · 1 chrome · 1b sidebar rail · 1c indigo sidebar
   1d topbar controls · 1e notifications · 1f phone preview
   2 grid + toolbar · 3 sla · 4 approval queue · 5 drawer detail
   6 forms · 7 admin · 8 dark mode · 9 responsive · 9b touch targets
   ============================================================ */

/* == 0. accent ==
   Deskgrid's accent is indigo, not the kit's yellow. assets/app.css is a
   verbatim copy of the shared kit and is never edited, so the accent is
   re-pointed here by overriding the VALUES of the tokens the kit declares on
   :root. The names are kept, so every rule in app.css keeps working.

   The one structural difference: yellow was a light fill carrying ink text.
   Indigo is a dark fill, so --on-amber is white. Measured contrast:

     #FFFFFF on #4B4FCE (fill) ............ 6.35:1   (ink would be 2.80:1)
     #FFFFFF on #3C40B6 (fill hover) ...... 8.07:1
     #4A41C4 (deep)   on #FFFFFF .......... 7.38:1
     #4A41C4 (deep)   on #EFECFD (soft) ... 6.36:1
     #332B8E (darker) on #FFFFFF .......... 11.19:1
     #17181A (ink)    on #EFECFD (soft) ... 15.30:1
   Dark theme, on --surface #191A1D:
     #ADA5F8 (deep) ....................... 7.88:1
     #C9C3FC (darker) .................... 10.52:1
     #F2F2F0 (ink) on #221D40 (soft) ..... 14.22:1

   The accent sits at hue 238–250°; --info is 211°, so a selected row and an
   info pill stay a clear third of the wheel apart, tint included. */
:root{
  --amber:#4B4FCE;       --amber-deep:#4A41C4;   --amber-darker:#332B8E;
  --amber-fill:#4B4FCE;  --amber-fill-hi:#3C40B6;
  --amber-soft:#EFECFD;  --amber-line:#CBC4F3;   --on-amber:#FFFFFF;
  /* --hover is the accent's own tint, so it moves with it */
  --hover:#F5F4FE;
}
[data-theme="dark"]{
  --amber-soft:#221D40;  --amber-line:#3D356F;
  --amber-deep:#ADA5F8;  --amber-darker:#C9C3FC;
  --hover:#201E33;
}
/* the kit paints selections with ink on the fill, which only worked while the
   fill was yellow */
::selection{background:var(--amber-fill);color:var(--on-amber)}
/* The kit draws the focus ring in --amber, which does not move between
   schemes. Indigo on the near-black dark ground is 2.88:1 — under the 3:1 a
   focus indicator has to reach — so dark mode takes the lifted shade instead.
   Placed here so the two subtrees that need a white ring (the indigo sidebar,
   the phone stage) still win it back further down. */
[data-theme="dark"] :focus-visible{outline-color:var(--amber-deep)}

/* == 1. chrome == */
.noscript{margin:16px;padding:12px 14px;border:1px solid var(--amber-line);background:var(--amber-soft);border-radius:var(--r);font-family:var(--sans);font-size:14px;color:var(--ink-2)}
.topbar__stack{display:flex;flex-direction:column;justify-content:center;min-width:0;line-height:1.25}
.side-scrim{position:fixed;inset:0;background:rgba(23,24,26,.42);z-index:64}
.who{display:flex;align-items:center;gap:9px;min-width:0;margin-bottom:10px}
.foot-stats{display:flex;gap:10px;font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);margin-bottom:10px}
/* A card caption can be a long sentence ("Expense claims and asset requests").
   Held on one line it walks straight out of the card — and off the page at
   360px, which is where the document picked up its 7px of sideways scroll.
   The head wraps and the caption is allowed to break, so it shrinks into the
   room the title leaves instead of overflowing it. */
.card__head{flex-wrap:wrap}
.card__head .label{min-width:0;white-space:normal}
/* label kept for assistive tech on a control that shows only a glyph */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.about__item{border-top:1px solid var(--line);margin-top:14px;padding-top:14px}
.about__item h4{margin-bottom:4px}
.about__list{margin:6px 0 0;padding-left:0}
.about__list li{position:relative;padding-left:15px;line-height:1.5}
.about__list li+li{margin-top:5px}
.about__list li::before{content:"";position:absolute;left:2px;top:8px;width:5px;height:5px;background:var(--amber);border-radius:1px}
.about__point+.about__point{margin-top:10px}
.about__point-title{font-size:13px;font-weight:600;margin-bottom:2px}
/* worked examples for the assistant: what you type, then what it does */
.about__ex{margin-top:10px}
.about__ex li+li{margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.about__ex-title{font-size:13px;font-weight:600}
.about__ex-ask{display:block;font-size:12px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);padding:5px 8px;margin:4px 0 5px;word-break:break-word}

/* == 1b. sidebar rail, app side ==
   app.css collapses the shared chrome. These are the Deskgrid-only bits of
   the footer that have no meaning at 64px: the signed-in identity and the
   record/breach stat line. */
.shell.is-rail .who{justify-content:center}
.shell.is-rail .who>div,
.shell.is-rail .foot-stats{display:none}

/* The footer is "About this demo" across the top, then two paired rows: the
   outbound links, then install beside reset. The rows carry the block rhythm,
   so nothing inside one needs a margin of its own. Only the author's site is
   inverted; the source link is an ordinary outline control. */
.side__foot .side__pair{margin-top:8px}
.sitelink{color:#fff}

/* == 1c. indigo sidebar ==
   app.css draws the brand sidebar for a light fill: ink text, dark hairlines,
   a white pill for the active link. Indigo is a dark fill, so the whole
   subtree flips to white text and light hairlines.

   The palette is pinned on the element — the pattern app.css already uses for
   this subtree in dark mode — and the pin is repeated at [data-theme="dark"]
   specificity so the kit's dark-mode re-pin cannot win. Indigo is a fixed
   surface: the sidebar reads identically in both themes.

     #FFFFFF on #4B4FCE ............ 6.35:1  (brand name, nav links)
     #E3E2FB on #4B4FCE ............ 5.00:1  (--ink-2: tag, group labels)
     #DAD9F9 on #4B4FCE ............ 4.62:1  (--muted/--faint, nav icons)
     #332B8E on #FFFFFF ........... 11.19:1  (active pill, footer buttons)  */
.side[data-tone="amber"],
[data-theme="dark"] .side[data-tone="amber"]{
  /* `color` is resolved once on body, so re-pointing --ink here does not reach
     text that simply inherits — the signed-in name in the footer stayed ink and
     landed on indigo at 2.80:1. Re-resolving it on the subtree root fixes every
     inheriting descendant at once. */
  color:var(--ink);
  --ink:#FFFFFF;   --ink-2:#E3E2FB;   --muted:#DAD9F9;   --faint:#DAD9F9;
  --bg:#FFFFFF;    --surface:#FFFFFF; --surface-2:#FFFFFF;
  --line:rgba(255,255,255,.20);       --line-2:rgba(255,255,255,.30);
  --hover:rgba(255,255,255,.12);
  --amber-deep:#4A41C4;               --amber-darker:#332B8E;
  --night:#17181A; --night-2:#222427; --night-ink:#F2F2F0;
}
/* the kit's hairlines here are ink at 16%, which vanishes on indigo */
.side[data-tone="amber"] .side__brand,
.side[data-tone="amber"] .side__foot,
.side[data-tone="amber"] .navgroup+.navgroup{border-color:rgba(255,255,255,.20)}
/* nav icons: --amber-darker is a dark violet now, so it cannot sit on indigo */
.side[data-tone="amber"] .navlink svg{color:#DAD9F9}
.side[data-tone="amber"] .navlink:hover{background:rgba(255,255,255,.12)}
/* the active pill stays white, but its label has to stop being --ink (white) */
.side[data-tone="amber"] .navlink.is-active{background:#FFFFFF;color:var(--amber-darker)}
.side[data-tone="amber"] .foot-stats{color:var(--ink-2)}
/* the identity chip echoes the brand mark: white block, indigo initials */
.side[data-tone="amber"] .avatar--amber{background:var(--ink);border-color:var(--ink);color:var(--amber-fill)}
/* footer and brand controls: light chips with indigo labels. The kit's rule
   pairs a near-white background with var(--ink), which is white here. */
.side[data-tone="amber"] .btn,
.side[data-tone="amber"] .side__brandbtns .btn{background:rgba(255,255,255,.90);border-color:rgba(255,255,255,.90);color:var(--amber-darker)}
.side[data-tone="amber"] .btn:hover,
.side[data-tone="amber"] .side__brandbtns .btn:hover{background:#FFFFFF;border-color:#FFFFFF}
.side[data-tone="amber"] .btn--dark,
.side[data-tone="amber"] .btn--dark:hover{color:#fff}
.side[data-tone="amber"] .btn--dark{background:var(--night);border-color:var(--night)}
.side[data-tone="amber"] .btn--dark:hover{background:var(--night-2);border-color:var(--night-2)}

/* == 1d. topbar controls ==
   Three icon-only controls and one labelled button, right of the page title:
   notifications, device preview, light/dark, About. */
.topbar__tools{display:flex;align-items:center;gap:6px;flex:none}
.topbar__notif{position:relative;display:flex}
.topbar__bell{position:relative}
.topbar__bell.has-unread svg{color:var(--amber-deep)}
.topbar__count{position:absolute;top:1px;right:0;min-width:16px;height:16px;padding:0 4px;border-radius:var(--r-pill);background:var(--bad);color:#fff;font-size:9.5px;font-weight:700;line-height:16px;text-align:center;letter-spacing:0}
.topbar__devices{display:flex;gap:2px;border:1px solid var(--line);border-radius:var(--r);padding:2px}
.topbar__devices .btn{width:30px;height:30px;padding:0}
.topbar__devices .btn.is-on{background:var(--amber-soft);border-color:var(--amber-line);color:var(--amber-deep)}
.topbar__about{white-space:nowrap}

/* == 1e. notifications ==
   A panel hung off the bell. Every line pairs its colour with a word, so the
   state never depends on colour alone. */
.notif{position:absolute;top:calc(100% + 10px);right:0;z-index:72;width:min(380px,calc(100vw - 24px));background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-3);overflow:hidden}
.notif__head{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--line);background:var(--surface-2)}
.notif__list{max-height:min(420px,60vh);overflow-y:auto}
.notif__list li+li{border-top:1px solid var(--line)}
.notif__item{display:flex;gap:10px;width:100%;text-align:left;background:none;border:0;padding:11px 14px;cursor:pointer;font:inherit;color:inherit}
.notif__item:hover{background:var(--hover)}
.notif__item.is-read{background:var(--surface)}
.notif__item.is-read .notif__title{font-weight:500;color:var(--muted)}
.notif__item.is-read .notif__dot{opacity:.4}
.notif__dot{width:8px;height:8px;border-radius:50%;flex:none;margin-top:6px;background:var(--faint)}
.notif__dot--bad{background:var(--bad)}
.notif__dot--warn{background:var(--warn)}
.notif__dot--info{background:var(--info)}
.notif__body{display:flex;flex-direction:column;gap:2px;min-width:0}
.notif__word{font-size:9.5px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.notif__title{font-size:13.5px;font-weight:600;line-height:1.35}
.notif__empty{padding:26px 20px;text-align:center}
.notif__emptymark{width:34px;height:34px;margin:0 auto 10px;border-radius:var(--r);border:1px solid var(--line);background:var(--surface-2);display:grid;place-items:center;color:var(--faint)}
.notif__emptymark svg{width:18px;height:18px}
.notif__foot{padding:10px 14px;border-top:1px solid var(--line);background:var(--surface-2)}

/* == 1f. phone preview ==
   The app in an iframe at 390 × 844 inside a dark bezel, on the brand indigo.
   White on indigo, always — the palette inside the surround is pinned so it
   reads the same in dark mode. */
.device{position:fixed;inset:0;z-index:90;overflow:auto;padding:18px;background:var(--amber-fill);color:var(--on-amber);
  --ink:#FFFFFF;--ink-2:#E3E2FB;--muted:#DAD9F9;--faint:#DAD9F9;--line:rgba(255,255,255,.22);--line-2:rgba(255,255,255,.32);--surface:#FFFFFF;--hover:#FFFFFF;
  --amber-deep:#4A41C4;--amber-darker:#332B8E}
.device__bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;width:100%;max-width:1080px;margin:0 auto}
.device__id{display:flex;align-items:center;gap:10px;flex:1;min-width:0}
.device .mark{background:var(--on-amber);color:var(--amber-fill)}
.device__name{font-weight:700;font-size:16px;letter-spacing:-.02em}
.device__sub{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-2)}
/* light chips with indigo labels, the same treatment as the sidebar footer —
   --on-amber is white here, so it cannot double as the label on a white chip */
.device .btn{background:rgba(255,255,255,.90);border-color:rgba(255,255,255,.90);color:var(--amber-darker)}
.device .btn:hover{background:#fff;border-color:#fff}
.device :focus-visible{outline-color:var(--on-amber)}
.device__stage{display:grid;place-items:center;padding:20px 0}
.device__bezel{background:#17181A;border:1px solid #000;border-radius:46px;padding:13px;box-shadow:var(--shadow-3);max-width:100%}
.device__screen{display:block;width:390px;height:844px;max-width:100%;border:0;border-radius:34px;background:#FFFFFF}
.device__note{max-width:60ch;margin:0 auto;text-align:center;color:var(--ink-2)}
html.is-devicelocked,html.is-devicelocked body{overflow:hidden}

/* == 2. data grid + toolbar == */
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.toolbar .search{min-width:220px}
.toolbar__sel{min-width:170px}
.stackrow{display:block}
.narrow{max-width:120px}
/* A table sitting straight on a card, with no bordered wrapper around it.
   Three or four columns of names and money have a minimum width the card
   cannot always give them — at 320px the submitter table on Reports pushed
   the whole page sideways. This is .tablewrap--scroll without the box: it
   costs nothing while the table fits, and hands it a scrollbar when it
   does not. */
.tablescroll{overflow-x:auto}
.grid-table td,.grid-table th{white-space:nowrap;padding-left:11px;padding-right:11px}
.grid-table td:nth-child(3){white-space:normal;min-width:190px}
tr.clickable{cursor:pointer}
tr.clickable:focus-visible{outline:2px solid var(--amber);outline-offset:-2px}
tr.is-sel td{background:var(--amber-soft)}
.cellcheck{width:38px}
.cellcheck input{width:15px;height:15px;accent-color:var(--amber);cursor:pointer}
.sortbtn{display:inline-flex;align-items:center;gap:5px;background:none;border:0;padding:0;cursor:pointer;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit}
.sortbtn:hover{color:var(--amber-deep)}
.sortbtn.is-on{color:var(--ink)}
.sortbtn__ar{font-size:10px;width:8px;display:inline-block}
.select--mini{padding:4px 26px 4px 8px;font-size:12.5px;border-radius:var(--r-sm);background-size:16px;background-position:right 6px center;min-width:88px}
.bulkbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px solid var(--amber-line);background:var(--amber-soft);border-radius:var(--r);padding:10px 14px}

/* == 3. sla tag == */
.sla{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;white-space:nowrap}
.sla .dot{width:7px;height:7px;border-radius:50%}
.sla--ok{color:var(--ok)}
.sla--warn{color:var(--warn)}
.sla--bad{color:var(--bad)}
.sla--done{color:var(--faint);font-weight:500}

/* == 4. approval queue == */
.queue{display:flex;flex-direction:column;gap:12px}
.qcard{display:flex;gap:16px;border:1px solid var(--line);border-left:4px solid var(--line-2);border-radius:var(--r-lg);background:var(--surface);padding:16px 18px}
.qcard--ok{border-left-color:var(--ok)}
.qcard--warn{border-left-color:var(--warn)}
.qcard--bad{border-left-color:var(--bad)}
.qcard__main{flex:1;min-width:0}
.qcard__main h3{font-size:15px}
.qcard__side{display:flex;flex-direction:column;gap:8px;width:150px;flex:none}
.qcard .timeline{margin-top:12px}
.linkbtn{background:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer;text-align:left;border-bottom:1px solid var(--amber-line)}
.linkbtn:hover{border-bottom-color:var(--amber)}

/* == 5. record drawer == */
.scrim--drawer{background:rgba(23,24,26,.42)}
.drawer__foot{display:flex;justify-content:flex-end;gap:8px;align-items:center;padding:12px 16px;border-top:1px solid var(--line);background:var(--surface-2);flex:none}
.kv{display:flex;flex-direction:column}
.kv__row{display:flex;gap:12px;align-items:baseline;padding:7px 0;border-bottom:1px solid var(--line)}
.kv__row:last-child{border-bottom:0}
.kv__k{flex:none;width:132px}
.kv__v{flex:1;min-width:0;font-size:13.5px;word-break:break-word}

/* == 6. forms == */
.fields{display:block}
.field--err .input,.field--err .select,.field--err .textarea{border-color:var(--bad)}
.err{font-size:12px;color:var(--bad);margin-top:5px}
.req{color:var(--amber-deep);margin-left:3px}
.prefixed{display:flex;align-items:stretch;border:1px solid var(--line-2);border-radius:var(--r);overflow:hidden}
.prefixed:focus-within{border-color:var(--amber)}
.prefixed__mark{display:grid;place-items:center;padding:0 11px;background:var(--surface-2);border-right:1px solid var(--line);color:var(--muted);font-size:13px}
.prefixed .input{border:0;border-radius:0}
.prefixed .input:focus{box-shadow:none}
.formfoot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}
.schemalist li+li{margin-top:10px;padding-top:10px;border-top:1px solid var(--line)}
.schemalist code{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-xs);padding:1px 5px}
.minilist li+li{margin-top:8px}
.minilist__btn{display:block;width:100%;text-align:left;background:none;border:1px solid var(--line);border-radius:var(--r);padding:9px 11px;cursor:pointer;font:inherit;color:inherit}
.minilist__btn:hover{background:var(--hover);border-color:var(--amber-line)}

/* == 7. admin == */
.fieldlist li+li{border-top:1px solid var(--line)}
.fieldrow{display:flex;align-items:center;gap:12px;padding:10px 0}
.fieldrow__main{flex:1;min-width:0}
.fieldrow__acts{display:flex;gap:2px;flex:none}
.fieldrow__acts .btn--icon{width:30px;height:30px;padding:6px}

/* == 8. dark mode ==
   app.css carries the palette. These are the Deskgrid pieces that need a
   second look on a dark ground. */
:root{color-scheme:light}
[data-theme="dark"]{color-scheme:dark}

/* The indigo sidebar is a fixed surface: #4B4FCE never changes with the
   theme, and it is already dark, so it keeps white text in both. Its palette
   is pinned in section 1c, at a specificity that outranks the kit's
   dark-mode re-pin — there is nothing left to correct here. */

/* the shared select chevron is drawn as a data URI in a light grey */
[data-theme="dark"] .select{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23A2A8B0' stroke-width='1.7'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E")}
/* scrims sit over a dark app, so they have to be darker than the app */
[data-theme="dark"] .side-scrim,
[data-theme="dark"] .scrim--drawer{background:rgba(0,0,0,.6)}
/* SLA words keep their own hue: the dark palette lifts ok/warn/bad to
   #5FCB97 / #E7B85C / #F08379, all above 4.5:1 on #191A1D, and every one is
   printed next to its word — On track, Due soon, Breached. */
[data-theme="dark"] .sla--done{color:var(--faint)}
/* charts: the muted bar has to stay visibly quieter than the amber one */
[data-theme="dark"] .bars__bar--muted{background:var(--line-2)}
[data-theme="dark"] .cellcheck input{accent-color:var(--amber-fill)}
[data-theme="dark"] .topbar__count{color:#17181A}
[data-theme="dark"] .sitelink{color:var(--night-ink)}

/* == 9. responsive == */
@media (max-width:900px){
  /* The rail is a desktop affordance. Below 900px the sidebar is already an
     off-canvas drawer at full width, so every rail rule has to stand down —
     and `.shell.is-rail` outranks the single-class `.shell` rule that turns
     the grid into one column, so each one is reverted by hand. */
  .shell.is-rail{grid-template-columns:minmax(0,1fr)}
  .shell.is-rail .side__name,
  .shell.is-rail .side__tag,
  .shell.is-rail .navgroup__label,
  .shell.is-rail .who>div{display:block}
  .shell.is-rail .foot-stats{display:flex}
  .shell.is-rail .navlink span,
  .shell.is-rail .navlink__count,
  .shell.is-rail .side__foot .btn span{display:inline}
  .shell.is-rail .side__brand{flex-direction:row;justify-content:flex-start;height:var(--bar);padding:0 18px;gap:10px}
  .shell.is-rail .side__brandbtns{margin-left:auto;flex-direction:row}
  .shell.is-rail .side__nav{padding:14px 12px}
  .shell.is-rail .navlink{justify-content:flex-start;padding:8px 10px}
  .shell.is-rail .navgroup+.navgroup{margin-top:18px;border-top:0;padding-top:0}
  .shell.is-rail .side__foot{padding:12px}
  .shell.is-rail .side__foot .btn{padding:5px 10px}
  .shell.is-rail .side__pair{flex-direction:row}
  .shell.is-rail .who{justify-content:flex-start}
  /* the sidebar is a full-width drawer here, so there is nothing to collapse */
  .side__brandbtns [data-chrome="rail"]{display:none}

  .qcard{flex-direction:column;gap:12px}
  .qcard__side{flex-direction:row;width:auto}
  .qcard__side .btn{flex:1}
}
@media (max-width:760px){
  /* The phone preview is a desktop affordance. At this width you are already
     looking at the layout it would show you. */
  .topbar__devices{display:none}
}
@media (max-width:640px){
  /* the topbar has to hold a menu button, a title and three controls at
     390px, so About drops to its glyph and the title stops pushing */
  .topbar{padding:0 12px;gap:8px}
  .topbar__about span{display:none}
  .topbar__about{width:32px;height:32px;padding:0;justify-content:center}
  .topbar__title,.topbar__sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .topbar__sub{display:none}
  /* the bell is not the rightmost control, so anchoring the panel to it
     pushes the left edge off screen at this width — pin it to the viewport */
  .notif{position:fixed;top:calc(var(--bar) + 8px);left:12px;right:12px;width:auto}
  .device{padding:12px}
  .device__bezel{border-radius:30px;padding:8px}
  .device__screen{border-radius:24px}

  /* Narrow-screen sideways scroll on Dashboard and Reports. Both causes sit in
     the shared sheet: .bars__col is a flex child with the default min-width of
     auto, so a long money label under a bar refuses to shrink; and table.data
     headers are nowrap, which a four-column card table cannot afford at 390px.
     Fixed app-side here — the records grid keeps nowrap, it scrolls in its own
     wrapper. Worth lifting into the kit so the sibling apps get it too. */
  .bars__col{min-width:0}
  .bars__x{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .card table.data:not(.grid-table) th{white-space:normal}
  .card table.data:not(.grid-table) th,
  .card table.data:not(.grid-table) td{padding-left:10px;padding-right:10px}

  /* at phone width there is no room to set a caption beside a title, so it
     takes the line under it — buttons in a card head are left alone */
  .card__head>.label{flex-basis:100%}

  /* the kit now gives the search box the whole first row at this width, so the
     toolbar reads as stacked bands: search, then the two filters sharing a
     line, then the status chips, then the count */
  .toolbar__sel{min-width:0;flex:1 1 calc(50% - 5px)}
  .toolbar .row{flex-basis:100%}
  .toolbar .spacer{display:none}
  .toolbar>.label{flex-basis:100%}
  .kv__row{flex-direction:column;gap:2px}
  .kv__k{width:auto}
  .side-scrim{z-index:64}
  .bulkbar{gap:8px}

  /* the assistant launcher is pinned bottom-right, and so is the toast stack —
     on a phone the toast lands squarely on top of it. Toasts move up over the
     launcher instead of covering it. */
  .toasts{right:12px;bottom:calc(22px + 52px + 12px)}
  .toast{max-width:calc(100vw - 24px)}
}

/* == 9b. touch targets ==
   Below 900px the app is being driven by thumb. Nothing here changes a
   colour, a border or a font — only the padding that decides how big a
   control is to press. The numbers stop short of 44px where a bigger box
   would break the row it sits in (the topbar holds five controls at 320px). */
@media (max-width:900px){
  .navlink{padding:10px}
  .side__foot .btn--sm{padding:9px 10px}
  .side__brandbtns .btn{width:34px;height:34px}
  .chip{padding:7px 11px}
  .tab{padding:11px 14px}
  .btn--sm{padding:8px 12px}
  .select--mini{padding:7px 26px 7px 8px}
  .cellcheck input{width:18px;height:18px}
  .fieldrow__acts .btn--icon{width:36px;height:36px;padding:8px}
  /* a sort control is only as tall as its label. The padding gives it a
     thumb-sized press area; the matching negative margin keeps the header
     row the height it already was. */
  .sortbtn{padding:7px 0;margin:-6px 0}
}
@media (max-width:640px){
  /* only once the device switch is gone and About is a glyph is there room
     to grow the chrome controls — at 768 they still share the row with a
     segmented control and a labelled button */
  .sidebtn,.topbar__notif .btn--icon,.topbar__tools>.btn--icon{width:40px;height:40px}
  .topbar__about{width:40px;height:40px}
}
@media (max-width:390px){
  .page-head h1{font-size:20px}
  .stat__value{font-size:22px}
  /* five controls and a title on one 320px line: the topbar loses its gap
     before it loses a press target */
  .topbar{gap:4px}
}
