/* Client portal engine. One stylesheet for every client.

   TOKENS, NOT COLOURS. Nothing below names a client's hue directly. The values
   in :root are the MINA house style (navy #00155D, sky #71B6FF). Each tenant
   ships `brand/brand.css`, loaded after this file, which overrides :root tokens
   and at most a handful of tenant specific rules. Panacea is teal and taupe
   taken from their own live site; 432 and the test clinic are MINA navy.

   The token families:
     --primary*   the brand hue. deep is buttons, deeper is the masthead and the
                  html ground, mid ends the login gradient, soft is the focus
                  ring, pale and line are tinted surfaces.
     --accent*    the second hue. accent and accent-deep are the glow in the
                  masthead; pale, line and ink are the warm "look at this" tint
                  used for new and draft pills and the standing notices.
     --*-rgb      space separated triplets of the same colours, so a shadow or a
                  glow can take an alpha: rgb(var(--shadow-rgb) / .3). */

:root {
  --primary:#102A78; --primary-deep:#00155D; --primary-deeper:#000C33; --primary-mid:#102A78;
  --primary-soft:#71B6FF; --primary-pale:#EAF3FF; --primary-line:#C7DEFB;

  --accent:#71B6FF; --accent-deep:#3F8FE8;
  --accent-pale:#FFF4E5; --accent-line:#FFD9A0; --accent-ink:#8A5200;

  --ink:#0B1B3D; --muted:#45557E; --faint:#8FA0CB;
  --line:#DCE5F3; --paper:#FFFFFF; --paper-2:#F3F7FD;

  --ok:#0F7B4F; --stale:#B45309; --alert:#B42318;
  --ok-pale:#E8F6EF; --ok-line:#B7E3CE;
  --warn-pale:#FFF6E8; --warn-line:#F5D9A8; --warn-ink:#7A4B00;
  --alert-pale:#FBEFED; --alert-line:#F0D4CF;

  --ink-rgb:11 27 61; --shadow-rgb:0 21 93; --accent-rgb:113 182 255;
  --line-rgb:199 222 251; --focus-rgb:113 182 255;

  /* The agency masthead runs darker than the client one. */
  --admin-top:#00081F;

  --sans:"Plus Jakarta Sans","SF Pro Text",-apple-system,BlinkMacSystemFont,sans-serif;
  --brand:"Montserrat","Plus Jakarta Sans",-apple-system,sans-serif;
  --brand-weight:800;
  --pill:999px; --r:14px; --r-lg:20px;
  --shadow:0 1px 2px rgb(var(--ink-rgb) / .05), 0 8px 24px -12px rgb(var(--ink-rgb) / .16);
  --shadow-lg:0 24px 60px -28px rgb(var(--shadow-rgb) / .42);
}

* { box-sizing:border-box; }
html,body { margin:0; padding:0; }

/* ------------------------------------------------- added to the home screen

   Five things that separate a web page from something that feels like an app.
   All pages get them, and all were verified on a simulated notch rather than
   assumed.

   1. html carries the masthead colour. In standalone iOS rubber-bands past the
      end of the page and shows whatever is BEHIND the body. With html
      transparent that was a flash of white above a dark masthead on every
      over-scroll. body keeps its own paper colour, so only the bounce sees this.

   2. overscroll-behavior stops the bounce propagating to the page at all. There
      is no pull-to-refresh in standalone, so nothing is lost.

   3. text-size-adjust stops iOS inflating body text when the phone is rotated
      into landscape, which otherwise breaks every line length on the page.

   4. tap-highlight off. The default is a grey box over whatever you touched,
      which no native app does. The buttons already have their own press state.

   5. See the inputs section for the one that actually bites: a field under 16px
      makes iOS ZOOM THE WHOLE PAGE when you tap it. */
html {
  background: var(--primary-deeper);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
html, body { overscroll-behavior-y: none; }

body {
  font-family:var(--sans); color:var(--ink); background:var(--paper-2);
  font-size:15px; line-height:1.6; -webkit-font-smoothing:antialiased;
  -webkit-tap-highlight-color: transparent;
  /* Fill the viewport even when the content does not. `html` carries the
     masthead colour so a top overscroll is not a flash of white, and without
     this that colour shows as a band under a short page. */
  min-height: 100vh;
  min-height: 100dvh;
}

/* Nothing in the furniture should be selectable on a long press, which on a
   phone reads as a bug rather than a feature. Message bodies and the client's
   own text stay selectable, because copying a reference out of a thread is a
   real thing people do. */
.top, .tabs, .btn, .pill, .lg-cap, .overline { -webkit-user-select:none; user-select:none; }
.nav, .seg, .sec-lbl { -webkit-user-select:none; user-select:none; }
a { color:var(--primary); }
button, input, select, textarea { font-family:inherit; font-size:inherit; color:inherit; }

/* ---------------------------------------------------------------- shell */
.top {
  background:
    radial-gradient(120% 180% at 12% -40%, rgb(var(--accent-rgb) / .22) 0%, transparent 58%),
    linear-gradient(180deg, var(--primary-deeper) 0%, var(--primary-deep) 100%);
  color:#fff; position:sticky; top:0; z-index:40;
  border-bottom:1px solid rgb(var(--line-rgb) / .15);
  box-shadow:0 10px 30px -22px rgb(var(--shadow-rgb) / .9);
}
.top-in {
  max-width:1120px; margin:0 auto; padding:20px 22px;
  display:flex; align-items:center; gap:22px;
}
.top .spacer { flex:1; }
.top .btn.ghost { border-color:rgba(255,255,255,.25); color:#fff; }
.top .btn.ghost:hover { background:rgba(255,255,255,.08); border-color:rgba(255,255,255,.4); }
.who { font-size:.86rem; color:var(--primary-pale); }
.wrap { max-width:1120px; margin:0 auto; padding:26px 22px 80px; }

/* The agency side runs a deeper masthead so a screen share never leaves any
   doubt about which side you are looking at. */
body.agency .top {
  background:
    radial-gradient(120% 180% at 12% -40%, rgb(var(--accent-rgb) / .13) 0%, transparent 58%),
    linear-gradient(180deg, var(--admin-top) 0%, var(--primary-deeper) 100%);
}

/* ---------------------------------------------------------------- type */
h1 { font-family:var(--brand); font-size:1.6rem; font-weight:var(--brand-weight); letter-spacing:-.018em; margin:0 0 4px; line-height:1.25; }
h2 { font-family:var(--brand); font-size:1.05rem; font-weight:700; margin:0 0 10px; }
.sub { color:var(--muted); margin:0 0 22px; }
.overline {
  font-size:.68rem; font-weight:700; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); margin:0 0 8px;
}

/* ---------------------------------------------------------------- cards */
.card {
  background:var(--paper); border:1px solid var(--line); border-radius:22px;
  box-shadow:0 1px 2px rgb(var(--ink-rgb) / .04), 0 18px 44px -30px rgb(var(--shadow-rgb) / .30);
  padding:22px; margin-bottom:16px;
}
.card.tight { padding:16px 18px; }

/* ---------------------------------------------------------------- buttons */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  border-radius:var(--pill); border:1.5px solid transparent; cursor:pointer;
  font-weight:700; font-size:.92rem; padding:11px 22px; background:var(--primary-deep);
  color:#fff; transition:transform .14s ease, background .14s ease, box-shadow .14s ease;
  text-decoration:none; white-space:nowrap;
  box-shadow:0 10px 22px -14px rgb(var(--shadow-rgb) / .85);
}
.btn:hover { background:var(--primary); transform:translateY(-1px);
             box-shadow:0 14px 26px -14px rgb(var(--shadow-rgb) / .9); }
.btn:active { transform:none; }
.btn[disabled] { opacity:.5; cursor:not-allowed; transform:none; }
.btn.ghost { background:transparent; color:var(--primary-deep); border-color:var(--line); box-shadow:none; }
.btn.ghost:hover { background:var(--primary-pale); border-color:var(--primary-line); }
.btn.sm { padding:7px 15px; font-size:.84rem; }
.btn.lg { padding:13px 26px; font-size:.98rem; min-height:48px; }
.btn.danger { background:var(--alert); }
.btn.go { background:var(--ok); }
.btn.go:hover { background:var(--ok); filter:brightness(1.08); }
.btn.quiet { background:transparent; border-color:transparent; box-shadow:none; color:var(--muted); }
.btn.quiet:hover { background:var(--paper-2); color:var(--ink); }

/* ---------------------------------------------------------------- forms */
label.f { display:block; margin:0 0 16px; }
label.f > span {
  display:block; font-size:.8rem; font-weight:700; color:var(--muted);
  margin-bottom:6px; letter-spacing:.01em;
}
label.f .hint { display:block; font-weight:500; color:var(--faint); font-size:.78rem; margin-top:-4px; margin-bottom:6px; }
/* A hint that belongs to the control ABOVE it, not below. Sits tight under its
   own select so a reader is never guessing which of two dropdowns it explains. */
label.f .underhint {
  display:block; font-weight:500; color:var(--faint); font-size:.78rem;
  line-height:1.5; margin:7px 2px 0; min-height:1.2em;
}
.inp, select.inp, textarea.inp {
  width:100%; padding:12px 14px; border:1.5px solid var(--line); border-radius:var(--r);
  background:var(--paper); transition:border-color .14s ease, box-shadow .14s ease;
}

/* THE ONE THAT ACTUALLY BITES ON A PHONE.
   iOS Safari ZOOMS THE ENTIRE PAGE IN when you focus an input whose font-size
   is under 16px, and it does not zoom back out afterwards. The body font here
   is 15px, so every field inherited 15px and tapping Username threw the layout
   sideways on every iPhone. There is no way to opt out of that behaviour short
   of disabling zoom entirely, which would be an accessibility failure. The only
   correct fix is to make the field 16px on touch devices.
   Desktop keeps 15px, where the problem does not exist. */
@media (hover: none) and (pointer: coarse) {
  .inp, select.inp, textarea.inp { font-size: 16px; }
}
.inp:focus, select.inp:focus, textarea.inp:focus {
  outline:none; border-color:var(--primary-soft); box-shadow:0 0 0 4px rgb(var(--focus-rgb) / .26);
}
textarea.inp { min-height:130px; resize:vertical; line-height:1.6; }
.row2 { display:grid; grid-template-columns:1fr 1fr; gap:0 16px; }
@media (max-width:640px){ .row2 { grid-template-columns:1fr; } }

/* ---------------------------------------------------------------- pills */
.pill {
  display:inline-flex; align-items:center; gap:6px; border-radius:var(--pill);
  padding:5px 12px; font-size:.74rem; font-weight:700; letter-spacing:.02em;
  background:var(--primary-pale); color:var(--primary-deep); border:1px solid var(--primary-line);
  white-space:nowrap; line-height:1.3;
}
.pill.new      { background:var(--accent-pale); border-color:var(--accent-line); color:var(--accent-ink); }
.pill.progress { background:var(--primary-pale); border-color:var(--primary-line); color:var(--primary-deep); }
.pill.waiting  { background:var(--alert-pale); border-color:var(--alert-line); color:var(--alert); }
.pill.done     { background:var(--ok-pale); border-color:var(--ok-line); color:var(--ok); }
.pill.closed   { background:#F1F2F4; border-color:var(--line); color:var(--muted); }
.pill.urgent   { background:var(--alert); border-color:var(--alert); color:#fff; }
.pill.internal { background:#F1F2F4; border-color:var(--line); color:var(--muted); }
.pill.draft    { background:var(--accent-pale); border-color:var(--accent-line); color:var(--accent-ink); }
.pill.warn     { background:var(--warn-pale); border-color:var(--warn-line); color:var(--warn-ink); }

/* Which company looks after this practice. Quiet, but never absent. */
.pill.ag       { background:transparent; border-color:var(--line); color:var(--faint);
                 font-weight:600; letter-spacing:.04em; text-transform:uppercase;
                 font-size:.64rem; padding:4px 9px; }

/* ---------------------------------------------------------------- list */
.tk {
  display:flex; align-items:flex-start; gap:14px; padding:17px 19px;
  border:1px solid var(--line); border-radius:18px; background:var(--paper);
  margin-bottom:10px; cursor:pointer; text-decoration:none; color:inherit;
  box-shadow:0 1px 2px rgb(var(--ink-rgb) / .04);
  transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease;
}
.tk:hover {
  border-color:var(--primary-soft); transform:translateY(-1px);
  box-shadow:0 1px 2px rgb(var(--ink-rgb) / .05), 0 16px 32px -20px rgb(var(--shadow-rgb) / .36);
}
.tk .body { flex:1; min-width:0; }
.tk .subj { font-weight:700; margin-bottom:3px; font-size:1.02rem; letter-spacing:-.011em; }
.tk .meta { font-size:.82rem; color:var(--muted); }
.tk .rt { display:flex; flex-direction:column; align-items:flex-end; gap:7px; }
.tk .rt .pills { display:flex; gap:6px; flex-wrap:wrap; justify-content:flex-end; }
.tk .ago { font-size:.75rem; color:var(--faint); }
.ref { font-family:ui-monospace,"SF Mono",monospace; font-size:.78rem; color:var(--faint); }
@media (max-width:560px) {
  .tk { flex-direction:column; gap:10px; }
  .tk .rt { align-items:flex-start; width:100%; }
  .tk .rt .pills { justify-content:flex-start; }
}

/* ---------------------------------------------------------------- thread */
.msg { display:flex; gap:12px; margin-bottom:18px; }
.msg:last-child { margin-bottom:0; }
.msg .av {
  width:34px; height:34px; border-radius:50%; flex:0 0 auto; display:flex;
  align-items:center; justify-content:center; font-weight:800; font-size:.78rem;
  background:var(--accent-pale); color:var(--accent-ink); border:1px solid var(--accent-line);
  box-shadow:0 4px 10px -6px rgb(var(--shadow-rgb) / .45);
}
.msg.agency .av { background:var(--primary-deep); color:#fff; border-color:var(--primary-deep); }
.msg.system .av { background:var(--paper-2); color:var(--faint); border-color:var(--line); }
.msg .bub { flex:1; min-width:0; }
.msg .hd { font-size:.8rem; color:var(--muted); margin-bottom:5px; display:flex; gap:9px; align-items:center; flex-wrap:wrap; }
.msg .hd b { color:var(--ink); }
.msg .tx {
  background:var(--paper); border:1px solid var(--line); border-radius:16px;
  padding:13px 16px; white-space:pre-wrap; word-wrap:break-word; overflow-wrap:anywhere;
}
.msg.agency .tx { background:var(--primary-pale); border-color:var(--primary-line); }
.msg.system .tx { background:var(--paper-2); color:var(--muted); font-size:.9rem; }
.msg.pending .tx { background:var(--accent-pale); border-color:var(--accent-line); border-style:dashed; }
.msg.internal .tx { background:#F4F6F7; border-color:var(--line); border-style:dashed; color:var(--muted); }
.msg.scheduled .tx { background:var(--paper); border-style:dashed; color:var(--muted); }
.msg.scheduled .av { opacity:.6; }
/* Tony on the agency side: the same bubble as any teammate, with a ring so
   Dean can tell at a glance whose words he is reading. */
.msg.tony .av { background:var(--paper); color:var(--primary-deep); border:2px solid var(--primary-deep);
                font-family:var(--brand); font-size:.9rem; }
.msg .bub .inp.reply { margin-top:2px; }
.msg .acts { margin-top:10px; }
/* A message that arrived while the thread was open slides in rather than
   the whole thread repainting. */
.msg.arrive { animation: rise .42s cubic-bezier(.2,.7,.2,1) both; }
@keyframes rise { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }

/* ---------------------------------------------------------------- misc */
.err {
  background:var(--alert-pale); border:1px solid var(--alert-line); color:var(--alert);
  border-radius:var(--r); padding:11px 14px; margin-bottom:14px; font-size:.9rem;
}
.okmsg {
  background:var(--ok-pale); border:1px solid var(--ok-line); color:var(--ok);
  border-radius:var(--r); padding:11px 14px; margin-bottom:14px; font-size:.9rem;
}
/* A quiet standing notice, not an error. Used for the confidentiality note on
   the request form, which must be present but must not look like a warning. */
.note {
  background:var(--accent-pale); border:1px solid var(--accent-line); color:var(--accent-ink);
  border-radius:var(--r); padding:12px 15px; margin-bottom:18px; font-size:.85rem;
  line-height:1.55;
}
.note b { color:var(--accent-ink); }
.files { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.file {
  display:inline-flex; align-items:center; gap:7px; font-size:.82rem;
  background:var(--paper-2); border:1px solid var(--line); border-radius:var(--pill);
  padding:6px 13px; text-decoration:none; color:var(--primary-deep); font-weight:600;
  max-width:100%; overflow:hidden; text-overflow:ellipsis;
}
.file:hover { background:var(--primary-pale); border-color:var(--primary-line); }
.tabs { display:flex; gap:6px; margin-bottom:18px; flex-wrap:wrap; }
.tab {
  border:1.5px solid var(--line); background:var(--paper); border-radius:var(--pill);
  padding:7px 16px; font-size:.85rem; font-weight:700; cursor:pointer; color:var(--muted);
}
.tab.on { background:var(--primary-deep); border-color:var(--primary-deep); color:#fff; }
.hide { display:none !important; }
.spin { display:inline-block; width:15px; height:15px; border:2px solid rgba(255,255,255,.4);
  border-top-color:#fff; border-radius:50%; animation:sp .7s linear infinite; }
.btn.ghost .spin, .btn.quiet .spin { border-color:rgb(var(--ink-rgb) / .2); border-top-color:var(--primary-deep); }
@keyframes sp { to { transform:rotate(360deg); } }
.muted { color:var(--muted); }
.small { font-size:.84rem; }
.fine { font-size:.8rem; color:var(--muted); margin:8px 0 0; line-height:1.5; }
hr.sep { border:0; border-top:1px solid var(--line); margin:22px 0; }
.acts { display:flex; gap:10px; flex-wrap:wrap; align-items:center; }

/* ---------------------------------------------------------------- greeting */
.greet {
  font-family:var(--brand); font-weight:var(--brand-weight); letter-spacing:-.022em;
  font-size:1.62rem; margin:0 0 4px; color:var(--ink); line-height:1.25;
}
.greet .light { color:var(--muted); font-weight:600; }

/* ---------------------------------------------------------------- empty */
.empty {
  background:var(--paper); border:1px dashed var(--primary-line); border-radius:22px;
  padding:64px 26px; text-align:center; color:var(--faint);
}
.empty .ic {
  width:54px; height:54px; margin:0 auto 16px; border-radius:50%;
  background:var(--primary-pale); border:1px solid var(--primary-line);
  display:flex; align-items:center; justify-content:center;
  font-size:24px; color:var(--primary-deep);
}
.empty h2 { color:var(--ink); margin-bottom:6px; }
.empty p { margin:0 auto; max-width:34ch; }
.empty .btn { margin-top:18px; }

/* ---------------------------------------------------------------- site box */
.sitebox { display:flex; gap:12px; align-items:flex-start; }
.sitebox .dot { width:10px; height:10px; border-radius:50%; margin-top:7px; flex:0 0 auto;
                background:var(--faint); }
.sitebox .dot.ok { background:var(--ok); box-shadow:0 0 0 4px rgb(15 123 79 / .14); }
.sitebox .dot.bad { background:var(--alert); box-shadow:0 0 0 4px rgb(180 35 24 / .14); }

/* ============================================================== the lockup

   The client leads because it is their portal. Then a hairline, then the
   companies that actually serve this group, as the tenant names them. A
   masthead naming only one agency would be wrong for a group served by two.

   Everything stays legible down to 320px. Below 720 the marks drop to their
   icons, because wordmarks side by side on a phone are illegible wordmarks.

   A tenant with no logo gets a text wordmark and an initial, set in its brand
   font, and the same hide rules apply to those spans. */

.lockup { display:flex; align-items:center; gap:17px; text-decoration:none; color:#fff; }
.lockup img { display:block; width:auto; }
/* Marks are never compressed. `min-width:0` on the lockup let flex shrink the
   BOX below its content, the images spilled out of it and drew underneath the
   buttons. The lockup keeps its content width and the spacer gives way. */
.lockup > img, .lockup > span.lg-client-text, .lockup > span.lg-client-initial { flex:0 0 auto; }

/* Their mark. The Panacea source file is 258x72, so 34px on screen is 2x
   retina exactly. A tenant with a larger source may raise it in brand.css. */
.lg-client { height:34px; filter:drop-shadow(0 2px 8px rgba(0,0,0,.28)); }

/* No logo: the name, set as a wordmark. */
.lockup .lg-client-text {
  font-family:var(--brand); font-weight:var(--brand-weight); font-size:1.28rem;
  letter-spacing:-.025em; line-height:1; color:#fff; white-space:nowrap;
  text-shadow:0 2px 10px rgba(0,0,0,.25);
}
.lockup .lg-client-initial {
  width:34px; height:34px; border-radius:11px; align-items:center; justify-content:center;
  font-family:var(--brand); font-weight:var(--brand-weight); font-size:1.05rem; line-height:1;
  color:#fff; background:rgba(255,255,255,.12); border:1px solid rgba(255,255,255,.28);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12), 0 4px 14px -6px rgba(0,0,0,.4);
}

.lg-div {
  width:1px; height:36px; flex:0 0 auto; border-radius:1px;
  background:linear-gradient(180deg, transparent, rgb(var(--line-rgb) / .40), transparent);
}

.lg-house { display:flex; flex-direction:column; gap:6px; flex:0 0 auto; }
.lg-cap {
  font-size:.56rem; font-weight:700; letter-spacing:.19em; text-transform:uppercase;
  color:var(--primary-pale); opacity:.62; white-space:nowrap; line-height:1;
}
.lg-agencies { display:flex; align-items:center; gap:15px; }
.lg-agencies img { height:20px; opacity:.95; flex:0 0 auto; }
.lg-dot {
  width:3px; height:3px; border-radius:50%; flex:0 0 auto;
  background:rgb(var(--line-rgb) / .45);
}

/* Icon-only variants, hidden until the breakpoint. The element is named in the
   selector on purpose: `.lockup img` is (0,1,1) and a bare class is (0,1,0),
   so a bare rule would lose to it and the icons would render at full natural
   size beside the wordmarks on desktop. That exact bug cost a pass on 432. */
.lockup img.lg-client-icon,
.lockup img.lg-mina-icon,
.lockup img.lg-dmc-icon { display:none; }
.lockup span.lg-client-icon { display:none; }

/* The fleet link. On a phone the masthead is already carrying marks and two
   buttons, so the words collapse to the arrow and the tap target stays. */
#hub span[aria-hidden] { margin-right:2px; }
@media (max-width:560px) {
  #hub { font-size:0; padding:7px 10px; }
  #hub span[aria-hidden] { font-size:.95rem; margin:0; }
}

@media (max-width:720px) {
  .top-in { padding:12px 16px; gap:10px; }
  .lockup { gap:11px; }
  /* `.lockup img` is (0,1,1). A bare `.lg-client { display:none }` is (0,1,0)
     and LOSES to it, so the full wordmark kept rendering on a phone beside the
     icon and the two collided with the buttons. The hide rule has to carry the
     element, exactly like the icon rules above. The text fallbacks are spans
     and are written the same way so the pattern is obvious. */
  .lockup img.lg-client { display:none; }
  .lockup span.lg-client-text { display:none; }
  .lockup .lg-house { display:none; }
  .lockup img.lg-client-icon { display:block; height:31px;
                               filter:drop-shadow(0 2px 8px rgba(0,0,0,.28)); }
  .lockup span.lg-client-icon { display:flex; width:31px; height:31px; font-size:.98rem; }
  /* A tenant with a wordmark but no icon keeps its wordmark, smaller, rather
     than swapping a real logo for a letter. */
  .lockup:has(img.lg-client) span.lg-client-icon { display:none; }
  .lockup:has(span.lg-client-initial) img.lg-client { display:block; height:26px; }
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon { display:block; height:26px; opacity:.95; }
  .lg-div { height:28px; }
  .who { display:none; }
  .wrap { padding:20px 16px 70px; }
  /* Marks plus two buttons is a lot for 360px. The actions shrink first,
     because a button can afford to be smaller and a logo cannot. */
  .top .btn.sm { padding:7px 12px; font-size:.8rem; }
}
@media (max-width:400px) {
  .top-in { padding:13px 12px; gap:8px; }
  .lockup { gap:9px; }
  .lockup img.lg-client-icon { height:27px; }
  .lockup span.lg-client-icon { width:28px; height:28px; font-size:.9rem; border-radius:9px; }
  .lockup:has(span.lg-client-initial) img.lg-client { height:22px; }
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon { height:22px; }
  .lg-div { height:23px; }
  .top .btn.sm { padding:6px 10px; font-size:.75rem; letter-spacing:-.01em; }
  .wrap { padding:18px 13px 60px; }
}
@media (max-width:340px) {
  /* At 320 there is genuinely not room for every mark and two buttons. The
     agency icons drop and the client's mark stays, because the client's mark
     is the one a client needs to recognise. Ours are in the footer credit. */
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon,
  .lockup .lg-div { display:none; }
  .lockup img.lg-client-icon { height:26px; }
  .top .btn.sm { padding:6px 9px; font-size:.72rem; }
}

/* ------------------------------------------------------- login lockup */
.auth-lockup {
  display:flex; flex-direction:column; align-items:center; gap:24px;
  margin-bottom:28px;
}
.auth-client { height:58px; width:auto; display:block;
               filter:drop-shadow(0 4px 14px rgba(0,0,0,.34)); }
span.auth-client-text {
  height:auto; filter:none; font-family:var(--brand); font-weight:var(--brand-weight);
  font-size:2.05rem; letter-spacing:-.03em; line-height:1.1; color:#fff; text-align:center;
  text-shadow:0 4px 18px rgba(0,0,0,.3);
}
.auth-rule {
  width:150px; height:1px; border-radius:1px;
  background:linear-gradient(90deg, transparent, rgb(var(--line-rgb) / .38), transparent);
}
.auth-house { display:flex; flex-direction:column; align-items:center; gap:13px; }
/* The agency marks are lockups of their own, an icon plus type, and both sit
   at roughly 75% ink within their canvas. Matching total height therefore
   matches them optically too. */
.auth-agencies { display:flex; align-items:center; gap:26px; }
.auth-agencies img { height:26px; width:auto; display:block; opacity:.95; }
.auth-agencies .lg-dot {
  width:3px; height:3px; border-radius:50%; flex:0 0 auto;
  background:rgb(var(--line-rgb) / .40);
}
@media (max-width:480px) {
  .auth-client { height:46px; }
  span.auth-client-text { font-size:1.7rem; }
  .auth-agencies img { height:21px; }
  .auth-agencies { gap:18px; }
  .auth-rule { width:110px; }
}

/* ------------------------------------------------------- footer credit */
.credit {
  text-align:center; margin-top:40px; padding-top:22px;
  border-top:1px solid var(--line); color:var(--faint); font-size:.78rem;
  line-height:1.7;
}
.credit b { color:var(--muted); font-weight:700; }

/* ------------------------------------------------------- phone refinements */
@media (max-width:720px) {
  /* The primary action sits beside the heading on desktop. On a phone it should
     be a full width tap target directly under the intro. */
  #new-btn { width:100%; margin:4px 0 4px !important; padding:14px 22px; }
  .greet { font-size:1.42rem; }
  h1 { font-size:1.38rem; }
  .sub { margin-bottom:16px; }
  .tabs { margin-bottom:14px; }
  .credit { margin-top:30px; font-size:.74rem; }
  .card { padding:18px; border-radius:20px; }
}

/* Nothing may ever scroll the page sideways. */
html, body { max-width:100%; overflow-x:hidden; }

/* ============================================ iOS home screen safe areas

   Added to the home screen the manifest sets display:standalone and the meta
   sets apple-mobile-web-app-status-bar-style to black-translucent, which draws
   the page UNDERNEATH the status bar. Without the insets below the masthead
   sits behind the clock, the wifi icon and the battery.

   `viewport-fit=cover` in the viewport meta is what makes env() resolve at all.
   It is set on all three pages; without it every inset is zero and none of this
   does anything.

   THE INSETS GO THROUGH CUSTOM PROPERTIES, NOT env() DIRECTLY.

   Two reasons, both practical. A value used in eight places should be named
   once. And env() cannot be overridden, so a rule written with env() inline is
   UNTESTABLE: there is no way to simulate a notch and look at the result. With
   a token, a test can set --sat to 59px and photograph the clearance, which is
   exactly how the padding below was checked rather than assumed. */

:root {
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --gut: 22px;
}

/* The top inset goes on `.top`, NOT on `.top-in`. Padding the outer element
   means the masthead gradient fills the status bar strip behind the clock,
   which is what makes it look deliberate. Padding the inner one leaves a pale
   band above the header instead. */
.top { padding-top: var(--sat); }

.top-in {
  padding-left:  max(var(--gut), var(--sal));
  padding-right: max(var(--gut), var(--sar));
}

.wrap {
  padding-left:  max(var(--gut), var(--sal));
  padding-right: max(var(--gut), var(--sar));
  padding-bottom: calc(80px + var(--sab));
}

@media (max-width:720px) {
  :root { --gut: 16px; }
  .wrap { padding-bottom: calc(70px + var(--sab)); }
}
@media (max-width:400px) {
  :root { --gut: 13px; }
  .wrap { padding-bottom: calc(60px + var(--sab)); }
}

/* ------------------------------------- THE NON NOTCHED iPHONE GAP

   env() alone is NOT enough, and this is the bug that was actually reported.

   On an iPhone WITH a notch or Dynamic Island, standalone + black-translucent
   gives env(safe-area-inset-top) of 47 to 59px and everything above works.

   On an iPhone WITHOUT one, an SE or an 8, iOS still draws a 20px status bar
   OVER the page, but env(safe-area-inset-top) reports ZERO. So the masthead got
   no padding at all and the logo sat underneath the clock and the battery.

   The floor below closes that. max() means a notched phone keeps its real, much
   larger inset and only the devices that report nothing get the 20px they need.

   Scoped two ways so nothing else is touched:
     - display-mode: standalone, so a browser tab, where the real status bar is
       above the viewport rather than over it, is unaffected.
     - @supports (-webkit-touch-callout: none), which is true only on iOS
       Safari. Android standalone puts the status bar ABOVE the viewport and
       correctly reports a zero inset, so forcing a band there would be a
       20px strip of nothing. */

@media (display-mode: standalone) {
  @supports (-webkit-touch-callout: none) {
    .top { padding-top: max(var(--sat), 20px); }
    body.auth { padding-top: calc(24px + max(var(--sat), 20px)); }
  }
}
@media (display-mode: standalone) and (max-height: 700px) {
  @supports (-webkit-touch-callout: none) {
    body.auth { padding-top: calc(16px + max(var(--sat), 20px)); }
  }
}
@media (display-mode: standalone) and (max-height: 580px) {
  @supports (-webkit-touch-callout: none) {
    body.auth { padding-top: calc(12px + max(var(--sat), 20px)); }
  }
}

/* ======================================================= the login screen

   It does not use .top and .wrap, it centres a card in the viewport, so it
   carries its own insets and its own height behaviour.

   TWO BUGS LIVED HERE AND BOTH MADE IT SCROLL ON A PHONE.

   1. `min-height:100vh`. On mobile Safari 100vh is the viewport height WITHOUT
      the address bar and toolbar, which is TALLER than what you can actually
      see. `100dvh` is the dynamic height that accounts for the browser chrome.
      The 100vh line stays first as the fallback for anything without dvh.

   2. `align-items:center` on the body. When content is taller than the
      container, a centred flex item overflows in BOTH directions and the top
      of it becomes unreachable. The fix is auto margins on the item, which
      centre it when there is room and collapse to zero when there is not.

   Measured before the fix: the card needed 620px of viewport and an iPhone SE
   in Safari gives about 553. The height tiers below bring it under 500. */

body.auth {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top:    calc(24px + var(--sat));
  padding-bottom: calc(24px + var(--sab));
  padding-left:   max(24px, var(--sal));
  padding-right:  max(24px, var(--sar));
}

/* Centres when it fits, top-aligns when it does not. Never clips the logo. */
body.auth > .box { margin-block: auto; }

/* ------------------------------------------------- short screens

   Tiered on HEIGHT, not width, because this is a vertical fit problem. A tall
   phone keeps the generous spacing; only a short one gets compressed, and the
   safe-area part of the padding is never compressed because that is physical
   hardware, not taste. */

@media (max-height: 700px) {
  body.auth {
    padding-top:    calc(16px + var(--sat));
    padding-bottom: calc(16px + var(--sab));
  }
  .auth-lockup { gap: 15px; margin-bottom: 18px; }
  .auth-client { height: 48px; }
  .auth-house { gap: 9px; }
  .auth-agencies img { height: 22px; }
  .auth-agencies { gap: 20px; }
  .auth-rule { width: 120px; }
  .panel { padding: 24px 24px; }
  .panel label.f { margin-bottom: 13px; }
  .foot { margin-top: 15px; }
}

@media (max-height: 580px) {
  body.auth {
    padding-top:    calc(12px + var(--sat));
    padding-bottom: calc(12px + var(--sab));
  }
  .auth-lockup { gap: 11px; margin-bottom: 14px; }
  .auth-client { height: 40px; }
  .auth-house { gap: 7px; }
  .auth-agencies img { height: 19px; }
  .auth-agencies { gap: 16px; }
  .auth-rule { width: 96px; }
  .panel { padding: 19px 20px; }
  .panel h2 { font-size: 1rem; margin-bottom: 2px; }
  .panel .sub { margin-bottom: 14px !important; }
  .panel label.f { margin-bottom: 11px; }
  .panel .inp { padding: 10px 13px; }
  /* The strapline is the one thing here that carries no function. It is the
     first to go, and only once the screen is genuinely short. */
  .foot { display: none; }
}

@media (max-height: 470px) {
  /* Landscape on a phone. Nothing fits at this height, so stop pretending and
     let it scroll cleanly from the top rather than compressing into mush. */
  .auth-lockup { gap: 9px; margin-bottom: 12px; }
  .auth-client { height: 34px; }
  .auth-rule { display: none; }
  .auth-agencies img { height: 17px; }
}

/* ================================================================ agency side

   Everything below is used only by the agency page. It lives here rather than
   inline so the tenant tokens reach it and the asset stamp versions it. */

/* ---------------------------------------------------------------- view nav

   Four places Dean goes. On a desktop a row of tabs under the heading; on a
   phone a bar along the bottom edge, where the thumb already is, clear of the
   home indicator. */
.nav { display:flex; gap:6px; margin:0 0 22px; flex-wrap:wrap; }
.nav button {
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  border:1.5px solid var(--line); background:var(--paper); border-radius:var(--pill);
  padding:8px 16px; font-size:.86rem; font-weight:700; color:var(--muted);
}
.nav button svg { width:17px; height:17px; flex:0 0 auto; }
.nav button.on { background:var(--primary-deep); border-color:var(--primary-deep); color:#fff; }
.nav .count {
  min-width:19px; height:19px; padding:0 6px; border-radius:10px; font-size:.68rem;
  display:inline-flex; align-items:center; justify-content:center; line-height:1;
  background:var(--alert); color:#fff; font-weight:800;
}
.nav .count:empty { display:none; }

@media (max-width:720px) {
  .nav {
    position:fixed; left:0; right:0; bottom:0; z-index:45; margin:0; gap:2px; flex-wrap:nowrap;
    background:rgba(255,255,255,.94); -webkit-backdrop-filter:saturate(1.6) blur(16px);
    backdrop-filter:saturate(1.6) blur(16px);
    border-top:1px solid var(--line);
    padding:6px max(8px, var(--sal)) calc(6px + var(--sab)) max(8px, var(--sar));
  }
  .nav button {
    flex:1 1 0; flex-direction:column; gap:3px; border:0; background:transparent;
    border-radius:14px; padding:7px 2px 5px; font-size:.68rem; letter-spacing:.01em;
    color:var(--faint); position:relative; min-height:50px; min-width:0;
  }
  .nav button svg { width:22px; height:22px; }
  .nav button.on { background:transparent; color:var(--primary-deep); }
  .nav button.on svg { transform:translateY(-1px); }
  .nav .count { position:absolute; top:3px; left:calc(50% + 6px); min-width:17px; height:17px;
                font-size:.62rem; padding:0 5px; box-shadow:0 0 0 2px #fff; }
  body.has-nav .wrap { padding-bottom: calc(96px + var(--sab)); }
}

/* ---------------------------------------------------------------- view head */
.vhead { display:flex; align-items:flex-end; gap:12px 18px; flex-wrap:wrap; margin-bottom:18px; }
.vhead .grow { flex:1 1 260px; min-width:0; }
.vhead .sub { margin:0; }
.vhead .side { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }

/* ---------------------------------------------------------------- Tony status */
.tony-st {
  display:inline-flex; align-items:center; gap:8px; border-radius:var(--pill);
  padding:6px 13px 6px 11px; font-size:.8rem; font-weight:700; line-height:1.3;
  background:var(--paper); border:1px solid var(--line); color:var(--ink); white-space:nowrap;
}
.tony-st i { width:8px; height:8px; border-radius:50%; background:#A3AAB8; flex:0 0 auto; }
.tony-st.on i { background:#239A5B; box-shadow:0 0 0 3px rgb(35 154 91 / .18);
                animation: breathe 2.6s ease-in-out infinite; }
.tony-st.late i { background:#D38A12; box-shadow:0 0 0 3px rgb(211 138 18 / .18); }
.tony-st.off { color:var(--muted); }
@keyframes breathe { 50% { box-shadow:0 0 0 5px rgb(35 154 91 / .06); } }

/* ---------------------------------------------------------------- approval card */
.qgroup { margin:0 0 8px; }
.qgroup + .qgroup { margin-top:26px; }
.acard {
  background:var(--paper); border:1px solid var(--line); border-radius:22px;
  box-shadow:0 1px 2px rgb(var(--ink-rgb) / .04), 0 18px 44px -30px rgb(var(--shadow-rgb) / .32);
  margin-bottom:16px; overflow:hidden; position:relative;
}
.acard.urgent { border-color:var(--alert-line); }
.acard.urgent::before { content:""; position:absolute; left:0; right:0; top:0; height:3px; background:var(--alert); }
.acard.quiet { box-shadow:0 1px 2px rgb(var(--ink-rgb) / .04); }
.acard.gone { animation: fold .5s ease forwards; }
@keyframes fold { to { opacity:0; transform:scale(.98); } }

.acard-hd { padding:18px 20px 14px; cursor:pointer; }
.acard-meta { display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; font-size:.78rem; color:var(--muted); }
.acard-meta .sepdot { color:var(--faint); }
.acard-meta .pill { padding:3px 9px; font-size:.68rem; }
.acard h3 {
  font-family:var(--brand); font-weight:700; font-size:1.14rem; line-height:1.32;
  letter-spacing:-.012em; margin:8px 0 3px; color:var(--ink);
}
.acard-hd:hover h3 { color:var(--primary-deep); }
.acard-sub { font-size:.8rem; color:var(--faint); }

.acard-sec { padding:15px 20px; border-top:1px solid var(--line); }
.sec-lbl {
  display:block; font-size:.66rem; font-weight:800; letter-spacing:.11em; text-transform:uppercase;
  color:var(--faint); margin:0 0 7px;
}

.reading { display:flex; gap:12px; align-items:flex-start; }
.tav {
  width:30px; height:30px; border-radius:50%; flex:0 0 auto; display:flex; align-items:center;
  justify-content:center; font-family:var(--brand); font-weight:800; font-size:.86rem;
  color:var(--primary-deep); background:var(--paper); border:2px solid var(--primary-deep);
}
.reading .r-body { flex:1; min-width:0; }
.reading .r-sum { margin:0; font-weight:600; line-height:1.5; }
.reading .r-und { margin:5px 0 0; color:var(--muted); font-size:.9rem; line-height:1.55; }

.flag {
  display:flex; gap:10px; align-items:flex-start; margin-top:10px; line-height:1.45;
  background:var(--warn-pale); border:1px solid var(--warn-line); color:var(--warn-ink);
  border-radius:12px; padding:10px 12px; font-size:.86rem;
}
.flag svg { width:17px; height:17px; flex:0 0 auto; margin-top:1px; }
.flag.red { background:var(--alert-pale); border-color:var(--alert-line); color:var(--alert); }
.flag b { font-weight:800; }

.prop-sum { font-weight:700; font-size:1.02rem; line-height:1.45; }
.chips { display:flex; flex-wrap:wrap; gap:6px; margin-top:9px; }
.chips .pill { padding:4px 10px; font-size:.7rem; }
.pill.risk-read, .pill.risk-low { background:var(--ok-pale); border-color:var(--ok-line); color:var(--ok); }
.pill.risk-medium { background:var(--warn-pale); border-color:var(--warn-line); color:var(--warn-ink); }
.pill.risk-high { background:var(--alert-pale); border-color:var(--alert-line); color:var(--alert); }
.pill.conf { background:var(--paper-2); border-color:var(--line); color:var(--ink); }

ol.plan { list-style:none; counter-reset:plan; margin:12px 0 0; padding:0; }
ol.plan li {
  counter-increment:plan; position:relative; padding:3px 0 3px 32px; margin:0 0 4px;
  font-size:.9rem; line-height:1.5;
}
ol.plan li::before {
  content:counter(plan); position:absolute; left:0; top:3px; width:22px; height:22px;
  border-radius:50%; background:var(--primary-pale); border:1px solid var(--primary-line);
  color:var(--primary-deep); font-size:.7rem; font-weight:800;
  display:flex; align-items:center; justify-content:center;
}

.steps { margin-top:12px; display:grid; gap:8px; }
.step { border:1px solid var(--line); background:var(--paper-2); border-radius:13px; padding:10px 13px; }
.step-hd { display:flex; flex-wrap:wrap; gap:4px 10px; align-items:baseline; font-size:.74rem; color:var(--muted); }
.step-hd b { color:var(--ink); font-size:.8rem; }
.step-pv { margin-top:4px; font-size:.88rem; line-height:1.5; white-space:pre-wrap; overflow-wrap:anywhere; }

textarea.inp.reply { min-height:120px; background:var(--paper); line-height:1.55; overflow-y:auto; }
.quote {
  border-left:3px solid var(--primary-line); padding:4px 0 4px 14px; white-space:pre-wrap;
  overflow-wrap:anywhere; color:var(--ink); font-size:.92rem; line-height:1.55;
}

.acard-ft { padding:14px 20px 18px; border-top:1px solid var(--line); background:var(--paper-2); }
.acard-ft .fine { margin:0 0 12px; }

.state {
  display:flex; gap:11px; align-items:flex-start; border-radius:14px; padding:11px 14px;
  background:var(--primary-pale); border:1px solid var(--primary-line); color:var(--primary-deep);
  font-size:.9rem; line-height:1.45;
}
.state + .acts { margin-top:12px; }
.state .st-ic { width:9px; height:9px; border-radius:50%; background:currentColor; margin-top:6px; flex:0 0 auto; }
.state .st-ic.pulse { animation: pulse 1.4s ease-in-out infinite; }
.state b { display:block; font-weight:800; }
.state span { display:block; opacity:.9; }
.state.ok { background:var(--ok-pale); border-color:var(--ok-line); color:var(--ok); }
.state.bad { background:var(--alert-pale); border-color:var(--alert-line); color:var(--alert); }
.state.warn { background:var(--warn-pale); border-color:var(--warn-line); color:var(--warn-ink); }
.state.muted { background:#F1F2F4; border-color:var(--line); color:var(--muted); }
@keyframes pulse { 50% { opacity:.3; transform:scale(.8); } }

@media (max-width:720px) {
  .acard { border-radius:20px; }
  .acard-hd { padding:16px 16px 12px; }
  .acard-sec { padding:14px 16px; }
  .acard-ft { padding:14px 16px 16px; }
  .acard h3 { font-size:1.06rem; }
  /* The decision is the whole point of the card. On a phone it is a full width
     thumb target, with the lesser actions sharing a row beneath it. */
  .acard-ft .acts .btn.primary { flex:1 1 100%; }
  .acard-ft .acts .btn:not(.primary) { flex:1 1 0; padding-left:10px; padding-right:10px; }
  .msg .acts .btn { flex:1 1 0; }
}

/* ---------------------------------------------------------------- folds */
details.fold > summary {
  list-style:none; cursor:pointer; display:flex; align-items:center; gap:10px;
  -webkit-user-select:none; user-select:none;
}
details.fold > summary::-webkit-details-marker { display:none; }
details.fold > summary::after {
  content:""; width:8px; height:8px; margin-left:auto; flex:0 0 auto;
  border-right:2px solid var(--faint); border-bottom:2px solid var(--faint);
  transform:rotate(45deg) translateY(-2px); transition:transform .18s ease;
}
details.fold[open] > summary::after { transform:rotate(-135deg) translateY(-2px); }
details.fold > summary .sec-lbl { margin:0; }
details.fold .fold-in { padding-top:12px; }
pre.raw {
  margin:12px 0 0; padding:12px; border-radius:12px; background:var(--paper-2);
  border:1px solid var(--line); font-size:.74rem; line-height:1.5; overflow:auto;
  white-space:pre-wrap; overflow-wrap:anywhere; max-height:320px;
}
dl.kv { display:grid; grid-template-columns:auto 1fr; gap:6px 14px; margin:10px 0 0; font-size:.86rem; }
dl.kv dt { color:var(--faint); font-weight:700; }
dl.kv dd { margin:0; overflow-wrap:anywhere; }

/* ---------------------------------------------------------------- site health */
.sites { display:grid; grid-template-columns:repeat(auto-fill, minmax(340px, 1fr)); gap:14px; }
@media (max-width:720px) { .sites { grid-template-columns:1fr; } }
.site { margin:0; display:flex; flex-direction:column; gap:10px; }
.site-hd { display:flex; gap:14px; align-items:flex-start; }
.site-hd .grow { flex:1; min-width:0; }
.site-hd .nm { font-weight:800; font-size:1rem; line-height:1.35; }
.site-hd .dm { font-size:.8rem; color:var(--muted); overflow-wrap:break-word; }
.site-tags { display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; margin-top:8px; }
.site-tags .pill { padding:3px 10px; font-size:.7rem; }
.site-sum { margin:0; font-size:.9rem; line-height:1.5; }
.site-facts { display:flex; flex-wrap:wrap; gap:4px 14px; font-size:.78rem; color:var(--muted); }
.site-facts b { color:var(--ink); font-weight:700; }
.grade {
  width:46px; height:46px; border-radius:14px; flex:0 0 auto; display:flex; flex-direction:column;
  align-items:center; justify-content:center; font-family:var(--brand); font-weight:800;
  font-size:1.3rem; line-height:1; background:var(--paper-2); color:var(--faint); border:1px solid var(--line);
}
.grade small { font-family:var(--sans); font-size:.56rem; font-weight:700; margin-top:3px; opacity:.8; }
.grade.g-a, .grade.g-b { background:var(--ok-pale); border-color:var(--ok-line); color:var(--ok); }
.grade.g-c { background:var(--warn-pale); border-color:var(--warn-line); color:var(--warn-ink); }
.grade.g-d, .grade.g-e, .grade.g-f { background:var(--alert-pale); border-color:var(--alert-line); color:var(--alert); }
ul.findings { list-style:none; margin:10px 0 0; padding:0; display:grid; gap:7px; }
ul.findings li { display:flex; gap:9px; font-size:.85rem; line-height:1.45; }
ul.findings li i { width:8px; height:8px; border-radius:50%; margin-top:6px; flex:0 0 auto; background:var(--faint); }
ul.findings li.ok i, ul.findings li.pass i { background:var(--ok); }
ul.findings li.warn i { background:#D38A12; }
ul.findings li.fail i, ul.findings li.critical i, ul.findings li.bad i { background:var(--alert); }
ul.findings li .probe { font-weight:700; }

/* ---------------------------------------------------------------- settings */
.setrow { display:flex; gap:16px; align-items:center; justify-content:space-between; }
.setrow .grow { flex:1; min-width:0; }
.setrow b { font-size:1rem; }
.switch { position:relative; width:54px; height:32px; flex:0 0 auto; cursor:pointer; display:block; }
.switch input { position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
.switch span {
  position:absolute; inset:0; border-radius:20px; background:#D5DAE3; transition:background .2s ease;
  pointer-events:none;
}
.switch span::after {
  content:""; position:absolute; top:3px; left:3px; width:26px; height:26px; border-radius:50%;
  background:#fff; box-shadow:0 2px 6px rgba(0,0,0,.22); transition:transform .2s cubic-bezier(.3,.7,.3,1);
}
.switch input:checked + span { background:var(--ok); }
.switch input:checked + span::after { transform:translateX(22px); }
.switch input:focus-visible + span { box-shadow:0 0 0 4px rgb(var(--focus-rgb) / .35); }

.catrow { padding:16px 0; border-top:1px solid var(--line); }
.catrow:first-child { border-top:0; padding-top:4px; }
.catrow:last-child { padding-bottom:0; }
.cat-hd { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-bottom:9px; }
.cat-hd b { font-size:.95rem; margin-right:auto; }
.seg {
  display:grid; grid-template-columns:repeat(4, 1fr); gap:3px; padding:3px;
  background:var(--paper-2); border:1px solid var(--line); border-radius:14px;
}
.seg button {
  border:0; background:transparent; border-radius:11px; padding:8px 4px; min-height:44px;
  font-size:.78rem; font-weight:700; line-height:1.2; color:var(--muted); cursor:pointer;
  transition:background .14s ease, color .14s ease, box-shadow .14s ease;
}
.seg button:hover:not([disabled]):not(.on) { color:var(--ink); background:rgba(255,255,255,.6); }
.seg button.on {
  background:var(--paper); color:var(--primary-deep);
  box-shadow:0 1px 2px rgb(var(--ink-rgb) / .1), 0 4px 12px -6px rgb(var(--shadow-rgb) / .35);
}
.seg button[disabled] { opacity:.35; cursor:not-allowed; }
.seg.off button.on { color:var(--muted); }
.savebar { display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:4px; }
@media (max-width:720px) {
  .savebar { position:sticky; bottom:calc(72px + var(--sab)); z-index:30; background:var(--paper-2);
             padding:10px 0; }
  .savebar .btn { flex:1 1 100%; }
  .seg button { font-size:.74rem; padding:7px 2px; }
}

/* ---------------------------------------------------------------- toast */
.toast {
  position:fixed; left:50%; bottom:calc(24px + var(--sab)); z-index:60;
  transform:translate(-50%, 16px); opacity:0; pointer-events:none;
  background:var(--ink); color:#fff; border-radius:14px; padding:12px 18px;
  font-size:.88rem; font-weight:600; line-height:1.45; max-width:min(92vw, 460px); width:max-content;
  box-shadow:0 18px 40px -16px rgba(0,0,0,.5); transition:opacity .22s ease, transform .22s ease;
}
.toast.show { opacity:1; transform:translate(-50%, 0); }
.toast.bad { background:var(--alert); }
@media (max-width:720px) { body.has-nav .toast { bottom:calc(82px + var(--sab)); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation:none !important; transition:none !important; }
}
