/* The Remote Support Program — DARK GRAPE
   Chosen 2026-09-16 from a three-way comparison of the whole product. Navy ground, our
   signature purple kept so the site stays continuous with everything already shipped.

   TWO PURPLES, and the distinction matters everywhere below:
     --grape  is LIFTED, and is for anything that is TEXT on the dark ground. The print
              colour #7c3aed manages only 2.9:1 there and is unreadable.
     --fill   is the DEEP pair, and is for filled buttons and bars that carry white text,
              where the lifted purple would fail instead.
   Portal pages override both per tenant - see BrandPalette, which does the same split
   against this ground rather than against white. */
:root {
  --peach: #0b1016; --mist: #0e141c; --ice: #121a23;
  --ink: #eef3f8; --muted: #93a4b6; --line: rgba(255, 255, 255, .10);
  --card: #121a23; --solid: #17212c;
  --panel-hi: #1b2633;       /* raised: table heads, form fields, selected rows */

  --blue: #60a5fa; --green: #34d399; --pink: #fb7185; --purple: #c4b5fd; --orange: #fb923c;
  --grape: #a78bfa;          /* signature, LIFTED — text, links, headings; portal pages override per tenant */
  --grape-lite: #c4b5fd;     /* gradient partner for the signature colour */
  --grape-bright: #7c3aed;   /* the raw brand colour, for fills that carry no text */
  --grape-rgb: 167, 139, 250;/* same as --grape, for rgba() shadows and borders */
  --grape-dark: #ddd6fe;     /* hover goes LIGHTER on a dark ground, not darker */
  --fill: #6d28d9;           /* DEEP — filled buttons and bars that carry white text */
  --fill-lite: #7c3aed;
  --ok: #6ee7b7; --warn: #fcd34d; --bad: #fca5a5;

  --r-hero: 28px; --r-card: 24px; --r-btn: 18px; --r-input: 14px;
  --sh-hero: 0 20px 60px rgba(0, 0, 0, .45);
  --sh-card: 0 18px 45px rgba(0, 0, 0, .38);
  --sh-btn: 0 10px 20px rgba(0, 0, 0, .40);
  --sh-hover: 0 14px 28px rgba(0, 0, 0, .45);

  /* A dozen places raised a surface with a wash of WHITE, which is how you lift something off
     a dark ground — and is invisible on a light one. They are tokens now so both palettes get
     to say what "slightly raised" means. Added with the light palette, 2026-09-20: the light
     block is only half the job, and these were the other half. */
  --lift: rgba(255, 255, 255, .05);       /* barely there: alternate sections, code, chat bubbles */
  --lift-hi: rgba(255, 255, 255, .10);    /* a hover, a muted pill, a file button */
  --edge: rgba(255, 255, 255, .14);       /* the border of something you type into */
  --glow-1: rgba(124, 58, 237, .20);      /* the two washes that stop the page being a flat rectangle */
  --glow-2: rgba(96, 165, 250, .10);
  --top-bg: rgba(11, 16, 22, .88);        /* the sticky header: the ground at 88% */

  /* Tells the browser this is a dark page, so the controls IT draws follow: select popups,
     scrollbars, date pickers, spinners. Without it those stay light whatever we set. */
  color-scheme: dark;
}

/* ─────────────────────────────────────────────────────────────────────────────
   LIGHT — stage 3.6.9, 2026-09-20.

   Clint: nobody should be locked into somebody else's light or dark. Until now this
   stylesheet had ONE palette and `color-scheme: dark`, so there was nothing to switch
   TO — this block is the missing half, and the switch is the easy part.

   Dark stays the default above, deliberately. Every existing tenant and every signed-out
   visitor sees exactly what they saw yesterday; only somebody who asks for light gets it.

   Every token that appears above is redefined here. A palette that redefines most of them
   is worse than one palette, because the three it forgets become invisible text on a
   background nobody tested — and the way that is found is a customer squinting at a page.

   THE TWO PURPLES SWAP ROLES. On the dark ground --grape is the LIFTED purple for text
   and --fill is the deep one for filled buttons. On white that is backwards: the lifted
   #a78bfa manages about 2.2:1 on white and is unreadable, so text takes the DEEP purple
   and fills keep it too. Hover goes darker here, where on the dark ground it went
   lighter. See BrandPalette, which does the same split per tenant. */
:root[data-theme="light"] {
  --peach: #fdf6f0; --mist: #f6f4fb; --ice: #ffffff;
  --ink: #1b2430; --muted: #5a6b7d; --line: rgba(27, 36, 48, .12);
  --card: #ffffff; --solid: #ffffff;
  --panel-hi: #eef2fb;       /* raised: table heads, form fields, selected rows */

  --blue: #1d4ed8; --green: #047857; --pink: #be123c; --purple: #6d28d9; --orange: #c2410c;
  --grape: #6d28d9;          /* signature — DEEP here, because it is text on white */
  --grape-lite: #7c3aed;
  --grape-bright: #7c3aed;
  --grape-rgb: 109, 40, 217;
  --grape-dark: #4c1d95;     /* hover goes DARKER on a light ground, not lighter */
  --fill: #6d28d9;
  --fill-lite: #7c3aed;
  --ok: #047857; --warn: #b45309; --bad: #b91c1c;

  --sh-hero: 0 20px 60px rgba(27, 36, 48, .12);
  --sh-card: 0 18px 45px rgba(27, 36, 48, .10);
  --sh-btn: 0 10px 20px rgba(27, 36, 48, .12);
  --sh-hover: 0 14px 28px rgba(27, 36, 48, .18);

  /* Lifting on white means a wash of INK, not of white. The same four tokens, inverted. */
  --lift: rgba(27, 36, 48, .04);
  --lift-hi: rgba(27, 36, 48, .08);
  --edge: rgba(27, 36, 48, .18);
  --glow-1: rgba(124, 58, 237, .10);
  --glow-2: rgba(96, 165, 250, .10);
  --top-bg: rgba(253, 246, 240, .88);

  color-scheme: light;
}
* { box-sizing: border-box; }
html {
  min-height: 100%;
  background: var(--peach);
}
body {
  margin: 0; color: var(--ink); line-height: 1.6;
  font-family: Inter, "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
  min-height: 100vh;
  /* The warm peach-to-ice gradient cannot survive on a dark ground; two soft glows do the
     same job of stopping the page being a flat black rectangle. */
  background:
    radial-gradient(760px 420px at 18% -8%, var(--glow-1), transparent 62%),
    radial-gradient(620px 420px at 92% 108%, var(--glow-2), transparent 62%);
  background-attachment: fixed;
}
a { color: var(--grape); text-decoration: none; font-weight: 700; }
a:hover { color: var(--grape-dark); }
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 28px; }
h1, h2, h3 { line-height: 1.15; margin: 0 0 14px; letter-spacing: -.02em; }
h1 { font-size: 46px; font-weight: 900; }
h2 { font-size: 32px; font-weight: 900; }
h3 { font-size: 20px; font-weight: 800; }
p { margin: 0 0 14px; }
.muted { color: var(--muted); }
em { font-style: normal; color: var(--grape); }

/* ---------- header ---------- */
/* Its own token because it is the ground colour at 88% — a sticky bar that stays near-black on
   a light page is the most visible way to get a palette half-done. */
.top { background: var(--top-bg); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 20; }
.nav { display: flex; align-items: center; justify-content: space-between; min-height: 74px; gap: 16px; }
.brand { font-weight: 900; color: var(--ink); display: flex; align-items: center; gap: 11px; font-size: 16px; letter-spacing: -.01em; }
/* The logo (2026-10-27, docs/logo): its own lettering, one version per palette. */
.brand-logo { display: block; height: 36px; width: auto; }
:root:not([data-theme="light"]) .logo-on-light,
:root[data-theme="light"] .logo-on-dark { display: none; }
nav { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
/* The website's menu carries the light/dark switch too (2026-10-14): at 20px it wrapped the switch onto a second line. */
.section-public nav { gap: 16px; }
nav a { color: var(--ink); font-weight: 700; }
nav a:hover { color: var(--grape); }
form.inline { display: inline; margin: 0; }

/* The light/dark switch. A bordered pill with a glyph, because the first version was a plain
   nav link and read as a page rather than as a control — nobody found it. It uses --lift and
   --edge, so it is visible on both grounds without either palette naming a colour for it. */
.theme-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--edge); background: var(--lift);
  color: var(--ink); font: inherit; font-size: 13px; font-weight: 800;
  cursor: pointer; transition: background .12s ease, border-color .12s ease;
}
.theme-toggle:hover { background: var(--lift-hi); border-color: rgba(var(--grape-rgb), .45); color: var(--grape); }
/* inline-flex above would otherwise beat the hidden attribute: the sound button and the website's switch both start hidden. */
.theme-toggle[hidden] { display: none; }

/* ---------- buttons ---------- */
.btn {
  display: inline-block; padding: 13px 22px; border-radius: var(--r-btn); font-weight: 800; font-size: 15px;
  border: 1px solid rgba(var(--grape-rgb), .25); color: var(--grape); background: var(--lift);
  cursor: pointer; box-shadow: var(--sh-btn); transition: transform .12s ease, box-shadow .12s ease;
  font-family: inherit;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 14px 28px rgba(0, 0, 0, .45); color: var(--grape-dark); background: var(--lift-hi); }
.btn-accent { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff !important; border-color: transparent; box-shadow: 0 12px 26px rgba(var(--grape-rgb), .32); }
.btn-accent:hover { box-shadow: 0 18px 34px rgba(var(--grape-rgb), .40); }
.btn-lg { padding: 16px 30px; font-size: 17px; border-radius: 20px; }
.btn-sm { padding: 8px 14px; font-size: 13px; border-radius: 13px; }
.btn-danger { color: var(--bad); border-color: rgba(153, 27, 27, .25); }
.btn-danger:hover { color: var(--bad); background: rgba(153, 27, 27, .25); }

/* ---------- hero ---------- */
.hero { padding: 76px 0 56px; }
.hero .wrap { display: grid; grid-template-columns: 1fr 1.15fr; gap: 44px; align-items: center; }
.hero .cta { display: flex; gap: 14px; align-items: center; margin-top: 26px; flex-wrap: wrap; }
.hero small { display: block; margin-top: 16px; color: var(--muted); font-weight: 600; }

/* ---------- sections & cards ---------- */
.section { padding: 62px 0; }
.section.alt { background: var(--lift); }
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.grid2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 28px; align-items: start; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card); padding: 26px; box-shadow: var(--sh-card); }
.card .icon {
  width: 52px; height: 52px; border-radius: 16px; display: flex; align-items: center; justify-content: center;
  /* Dark ink, not white: these three fills are bright pastels, and white on #60a5fa is 2.2:1.
     The deep-purple fills elsewhere keep white — see the two-purple note at the top. */
  font-weight: 900; font-size: 20px; color: #0b1016; margin-bottom: 16px;
  background: linear-gradient(135deg, var(--blue), var(--purple)); box-shadow: 0 10px 22px rgba(96, 165, 250, .35);
}
/* Signup's choices (2026-11-03): people starting a trial did not see that the region and version boxes were buttons.
   Each box now has a purple edge, lifts on hover, and ends in a real filled button; the whole box is still the link. */
.pick-card { display: flex; flex-direction: column; cursor: pointer; border: 2px solid rgba(var(--grape-rgb), .45);
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease; }
.pick-card:hover, .pick-card:focus-visible { transform: translateY(-3px); border-color: var(--grape); outline: none;
  box-shadow: 0 0 0 4px rgba(var(--grape-rgb), .18), var(--sh-card); }
.pick-card .pick-body { flex: 1; }
.pick-go { display: block; margin-top: 16px; text-align: center; padding: 12px 16px; border-radius: 14px; font-weight: 800; font-size: 15px;
  background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff; box-shadow: 0 10px 22px rgba(var(--grape-rgb), .30); }
.pick-card:hover .pick-go { box-shadow: 0 14px 28px rgba(var(--grape-rgb), .42); }
.signup-steps { display: flex; gap: 6px; flex-wrap: wrap; list-style: none; padding: 0; margin: 4px 0 16px; font-size: 13px; font-weight: 800; }
.signup-steps li { padding: 5px 12px; border-radius: 999px; background: var(--lift-hi); color: var(--muted); }
.signup-steps li.on { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff; }
.signup-steps li.done { color: var(--grape); }
.btn[disabled] { opacity: .65; cursor: wait; transform: none; }
/* Owner → All companies (2026-11-03, HANDOVER §188): tabs with counts, a search, one line per company, its details beneath. */
.co-tools { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 14px 0 6px; }
.co-tools input[type=search] { flex: 1; min-width: 220px; margin: 0; }
.co-tools select { width: auto; margin: 0; }
.co-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 14px; }
.co-tabs a { font-size: 14px; font-weight: 800; padding: 7px 14px; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--muted); white-space: nowrap; }
.co-tabs a b { margin-left: 7px; font-size: 12px; padding: 1px 8px; border-radius: 999px; background: var(--lift-hi); color: var(--ink); }
.co-tabs a.on { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff; border-color: transparent; }
.co-tabs a.on b { background: rgba(255, 255, 255, .22); color: #fff; }
.co-tabs a.attn b { background: rgba(245, 158, 11, .25); color: var(--warn); }
.co-list { display: table; width: 100%; } /* a phone makes every table a block, which left these rows short of its edge */
.co-list td, .co-list th { padding: 0; }
.co-line { display: grid; grid-template-columns: minmax(0, 2.6fr) .9fr 1.4fr .7fr .8fr 1fr; gap: 12px; align-items: center; padding: 11px 16px; }
.co-list.several .co-line { grid-template-columns: minmax(0, 2.4fr) 1fr .9fr 1.4fr .7fr .8fr 1fr; }
.co-head .co-line { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.co-n { text-align: right; }
.co > summary { list-style: none; cursor: pointer; }
.co > summary::-webkit-details-marker { display: none; }
.co > summary:hover { background: var(--lift); }
.co > summary > span:first-child::before { content: "▸"; color: var(--muted); display: inline-block; width: 16px; }
.co[open] > summary > span:first-child::before { content: "▾"; }
.co[open] > summary { background: var(--lift); }
.co-why { display: block; margin-left: 16px; font-size: 12px; font-weight: 700; color: var(--warn); }
.co-detail { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 18px; padding: 6px 18px 18px 32px; background: var(--lift); font-size: 14px; }
.co-detail h4 { margin: 8px 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.co-pager { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 10px; font-size: 13px; color: var(--muted); }
@media (max-width: 700px) {
  .co-line, .co-list.several .co-line { grid-template-columns: minmax(0, 1fr) auto; }
  .co-sm { display: none; }
  .co-detail { padding-left: 18px; }
}
.grid3 .card:nth-child(2) .icon { background: linear-gradient(135deg, var(--green), var(--blue)); box-shadow: 0 10px 22px rgba(52, 211, 153, .35); }
.grid3 .card:nth-child(3) .icon { background: linear-gradient(135deg, var(--pink), var(--orange)); box-shadow: 0 10px 22px rgba(251, 113, 133, .35); }
.feature-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 11px 30px; }
.feature-list li { padding-left: 28px; position: relative; font-weight: 600; }
.feature-list li::before { content: "✓"; color: #10b981; position: absolute; left: 0; font-weight: 900; }
.quote { font-style: italic; color: #c6d3e1; }
.quote .who { font-style: normal; color: var(--muted); margin-top: 10px; font-size: 14px; font-weight: 700; }

/* ---------- pricing ---------- */
.price-card { text-align: center; border: 2px solid rgba(var(--grape-rgb), .35); }
.price { font-size: 52px; font-weight: 900; background: linear-gradient(135deg, var(--grape), var(--grape-lite)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.price small { font-size: 16px; color: var(--muted); font-weight: 700; -webkit-text-fill-color: var(--muted); }
.toggle { display: inline-flex; border-radius: 999px; overflow: hidden; margin-bottom: 24px; background: var(--lift); box-shadow: var(--sh-btn); padding: 5px; gap: 4px; }
.toggle button { border: 0; background: transparent; padding: 10px 20px; cursor: pointer; font-weight: 800; color: var(--muted); border-radius: 999px; font-family: inherit; font-size: 14px; }
.toggle button.on { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff; box-shadow: 0 8px 16px rgba(var(--grape-rgb), .3); }

/* New ticket's job types (2026-10-09): each in its own colour — --c, and --cd on a dark ground, from
   TicketSummary.CategoryColors — outlined, the chosen one filled with a tick. Clint: the wrong category had been
   chosen because the old strip did not show which was picked. */
.cat-pick { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; }
.cat-pick button { --ink-c: var(--cd); border: 2px solid var(--ink-c); background: transparent; color: var(--ink-c);
  padding: 10px 20px; border-radius: 999px; font-weight: 800; font-size: 15px; cursor: pointer; font-family: inherit; }
:root[data-theme="light"] .cat-pick button { --ink-c: var(--c); }
.cat-pick button:hover { background: color-mix(in srgb, var(--ink-c) 14%, transparent); }
.cat-pick button.on { background: var(--c); border-color: var(--c); color: #fff; box-shadow: 0 6px 14px rgba(0, 0, 0, .28); }
.cat-pick button.on::before { content: "✓ "; }

/* The portal's menu as tabs (2026-10-09): Clint — "mostly just text that one clicks on". Each link a rounded
   button, the page you are on filled (aria-current, set in _Layout). Only the portal's and the owner's menus
   (nav.tabs); the public site keeps its plain links. */
.top nav.tabs { gap: 8px; }
.top nav.tabs > a:not(.pill), .top nav.tabs > form > a {
  display: inline-block; padding: 6px 14px; border-radius: 999px; font-size: 14px; line-height: 1.3; white-space: nowrap;
  border: 1px solid rgba(var(--grape-rgb), .35); background: var(--lift); color: var(--ink); }
.top nav.tabs > a:not(.pill):hover, .top nav.tabs > form > a:hover { background: var(--lift-hi); border-color: var(--grape); color: var(--ink); }
.top nav.tabs > a[aria-current="page"] { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); border-color: transparent; color: #fff; }
.top nav.tabs > a.pill { margin-left: -4px !important; }
/* The portal's menu outgrew one sticky bar (Clint, 2026-11-01: "everything in the portal seems out of alignment"): 26 tabs
   wrapped to four rows, a 155 px header pinned over every page's heading, and the ticket list ran off its card at 1393 px.
   So the portal and owner pages use the screen's width, and on a computer the header scrolls away with the page. The
   phone's one-line header (below 700 px) stays pinned — its menu folds behind a button. */
.section-portal .wrap, .section-owner .wrap { max-width: 1480px; }
@media (min-width: 701px) { .section-portal .top, .section-owner .top { position: static; } }

/* ---------- forms ----------
   These apply to every input on the site, not only ones inside .form. Portal tables put bare
   selects and text boxes in rows - the role dropdown and the password reset box on the People
   page - and scoping the dark styling to .form left those rendering white. */
input:not([type=checkbox]):not([type=radio]):not([type=color]):not([type=file]),
select, textarea {
  background: var(--panel-hi); color: var(--ink);
  border: 1px solid var(--edge); border-radius: 10px;
  padding: 8px 11px; font-family: inherit; font-size: 14px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--grape); }

/* ---------- forms ---------- */
.form { max-width: 580px; }
.form label { display: block; font-weight: 800; margin: 16px 0 7px; font-size: 14px; }
.form input, .form select, .form textarea {
  width: 100%; padding: 13px 15px; border: 1px solid var(--edge); border-radius: var(--r-input);
  font-size: 15px; font-family: inherit; background: var(--panel-hi); color: var(--ink);
}
.form input:focus, .form select:focus, .form textarea:focus { outline: none; border-color: var(--grape); box-shadow: 0 0 0 4px rgba(var(--grape-rgb), .22); }
.form input::placeholder, .form textarea::placeholder { color: #5d6e80; }
.form input[type=color] { width: 68px; height: 46px; padding: 3px; cursor: pointer; }
.form input[type=checkbox] { width: auto; }
/* The native file-input button is drawn by the browser and stays light unless told otherwise. */
.form input[type=file]::file-selector-button {
  background: var(--panel-hi); color: var(--ink); border: 1px solid var(--edge);
  border-radius: 8px; padding: 7px 13px; margin-right: 11px; cursor: pointer; font: inherit; font-weight: 700;
}
.form input[type=file]::file-selector-button:hover { background: var(--lift-hi); }
.form .row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.form .actions { margin-top: 24px; }
.alert { padding: 14px 18px; border-radius: 16px; margin: 16px 0; font-weight: 600; border: 1px solid transparent; }
.alert-bad { background: rgba(239, 68, 68, .16); color: var(--bad); border-color: rgba(239, 68, 68, .3); }
.alert-ok { background: rgba(16, 185, 129, .16); color: var(--ok); border-color: rgba(16, 185, 129, .3); }
.alert-warn { background: rgba(245, 158, 11, .16); color: var(--warn); border-color: rgba(245, 158, 11, .3); }

/* The portal menu's Connect (2026-10-28): the phone and tablet page, offered on a touch screen. */
/* The menu's Connect and a ticket's Connect are shown on EVERY device (2026-10-28). They were hidden on a mouse-like pointer, then
   on a wide screen with one — and Clint's Samsung, which reports both, lost the link twice. Showing it everywhere is simpler, and a
   laptop with Windows Hello can use the page too. */
.phone-connect { margin-left: 8px; }
/* A ticket opened as a sheet over the phone's session: the ticket, nothing around it. */
.in-sheet header.top, .in-sheet .chat-launcher, .in-sheet .chat-panel, .in-sheet footer { display: none !important; }

/* ---------- passkeys (2026-10-28) ---------- passkey.js shows them only where the browser can use them */
.passkey-sign-in[hidden], #passkeyStart[hidden], [data-passkey-error][hidden], [data-no-passkeys][hidden] { display: none; }
.passkey-sign-in { margin-top: 8px; }
.passkey-or { text-align: center; margin: 4px 0 12px; }
.passkey-sign-in .btn { width: 100%; }
.passkey-note { font-size: 13px; margin-top: 10px; }
.passkey-list td, .passkey-list th { padding: 8px 6px; }

/* ---------- portal ----------
   Portal page titles carry the tenant SIGNATURE rather than plain ink. On the old white theme
   an ink heading read as near-black and looked deliberate; on navy it reads as plain white and
   leaves a tenant page with no brand colour anywhere on it. Only the page title - h2 and h3 are
   section labels inside cards and stay ink, or the page turns into noise. */
.section-portal .portal > .wrap > h1,
.section-portal h1,
.section-owner h1 { color: var(--grape); }

.portal { padding: 36px 0 56px; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 28px; }
.stat { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card); padding: 22px; box-shadow: var(--sh-card); }
.stat .n { font-size: 38px; font-weight: 900; background: linear-gradient(135deg, var(--grape), var(--grape-lite)); -webkit-background-clip: text; background-clip: text; color: transparent; line-height: 1.1; }
.stat .l { color: var(--muted); font-size: 14px; font-weight: 700; margin-top: 4px; }
table { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; box-shadow: var(--sh-card); }
th, td { text-align: left; padding: 14px 18px; border-bottom: 1px solid var(--line); font-size: 14px; }
th { background: var(--panel-hi); color: var(--grape); font-weight: 800; }
tr:last-child td { border-bottom: 0; }
.pill { display: inline-block; padding: 6px 14px; border-radius: 999px; font-size: 12px; font-weight: 800; }
.pill-ok { background: rgba(16, 185, 129, .16); color: var(--ok); }
.pill-warn { background: rgba(245, 158, 11, .16); color: var(--warn); }
.pill-bad { background: rgba(239, 68, 68, .16); color: var(--bad); }
.pill-muted { background: var(--lift-hi); color: var(--muted); }
.preview { border-radius: 20px; overflow: hidden; width: 370px; box-shadow: var(--sh-card); border: 1px solid var(--line); }
.preview .banner { height: 88px; display: flex; align-items: center; padding: 0 18px; color: #fff; font-weight: 900; font-size: 19px; }
.preview .banner img { max-height: 60px; max-width: 230px; }
.preview .pbody { padding: 18px; background: var(--panel-hi); }
.preview .pbtn { display: block; text-align: center; color: #fff; padding: 13px; border-radius: 14px; font-weight: 800; }
code { background: var(--lift); border: 1px solid var(--line); padding: 3px 9px; border-radius: 9px; font-size: 13px; font-family: Consolas, monospace; color: var(--grape); font-weight: 600; }
.copy { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* ---------- customer download page ---------- */
.getpage { text-align: center; padding: 76px 0; }
.getpage .tbanner { display: inline-block; padding: 26px 44px; border-radius: var(--r-hero); margin-bottom: 28px; color: #fff; box-shadow: var(--sh-hero); }
.getpage .tbanner img { max-height: 88px; max-width: 330px; }
.getpage .steps { text-align: left; max-width: 580px; margin: 34px auto 0; }
ol { line-height: 1.9; }

/* ---------- footer ---------- */
.foot { border-top: 1px solid var(--line); padding: 26px 0; color: var(--muted); font-size: 14px; font-weight: 600; background: rgba(0, 0, 0, .25); }
.foot .wrap { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }

@media (max-width: 900px) {
  h1 { font-size: 34px; } h2 { font-size: 26px; }
  .wrap { padding: 0 20px; }
  .hero .wrap, .grid3, .grid2, .stats, .form .row, .feature-list { grid-template-columns: 1fr; }
  .nav { flex-direction: column; padding: 14px 0; }
  nav { justify-content: center; gap: 16px; }
  .preview { width: 100%; }
  .foot .wrap { flex-direction: column; }
  table { display: block; overflow-x: auto; }
}
/* The website's menu never wraps to a second line (Clint, 2026-11-01): beside the logo it needs about 990 px with a scrollbar, so up to 1020 it sits on its
   own line under the logo, as it does below 900. The phone's Menu button takes over below 700. */
@media (min-width: 701px) and (max-width: 1020px) {
  .section-public .nav { flex-direction: column; padding: 14px 0; }
  .section-public nav { justify-content: center; gap: 16px; }
}

/* ---------- seats (pricing) ----------
   The seven seats, named rather than counted. Shared with the landing page's markup so the two
   stay visibly the same product; see docs/PRICING.md for why the naming matters commercially. */
.seats { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; text-align: left; }
.seats li {
  display: flex; align-items: flex-start; gap: 13px;
  background: var(--lift); border: 1px solid var(--line);
  border-radius: 16px; padding: 14px 16px;
}
.seats .n {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-weight: 900; font-size: 14px;
  background: rgba(var(--grape-rgb), .16); color: var(--grape);
}
.seats .t { font-weight: 800; display: block; font-size: 15px; }
.seats .d { color: var(--muted); font-size: 13.5px; display: block; margin-top: 2px; }
.extra-seat {
  margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line);
  color: var(--muted); font-size: 15px;
}
.extra-seat b { color: var(--ink); }
.rollout {
  margin: 26px auto 0; max-width: 780px;
  border: 1px solid rgba(var(--grape-rgb), .28); background: rgba(var(--grape-rgb), .07);
  border-radius: var(--r-card); padding: 18px 22px; font-size: 15px;
}
.rollout b { color: var(--grape); }

/* ---------- the people on a ticket (2026-09-28) ----------
   One pill-shaped tick box per person. Inside .form a label is a bold block with a margin, which
   is right for a field's name and wrong for a tick box, so both are said here. */
.people-label { display: block; font-weight: 800; font-size: 13px; margin: 10px 0 6px; }
/* In a .form it is one of the form's own labels, so it takes their size and spacing. */
.form .people-label { font-size: 14px; margin: 16px 0 7px; }
.people { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 4px; }
.people label.person, .form .people label.person {
  display: inline-flex; align-items: center; gap: 7px; margin: 0; padding: 7px 13px;
  border: 1px solid var(--edge); border-radius: 999px; background: var(--panel-hi);
  font-weight: 700; font-size: 14px; cursor: pointer; color: var(--ink);
}
.people label.person:has(input:checked) { border-color: var(--grape); background: rgba(var(--grape-rgb), .16); }
.people label.person.locked { opacity: .62; cursor: default; }
.people input[type=checkbox], .form .people input[type=checkbox] { width: auto; margin: 0; accent-color: var(--grape); }

/* ---------- a person's roles as tick boxes (2026-09-29, roadmap 3.6.8) ----------
   The same pills as the people on a ticket, smaller, and each kept whole, in two short lines at
   most. The cell is given that much room so the pills do not stack one per line. */
td.roles-cell { min-width: 290px; }
.people.roles-row { align-items: center; gap: 6px; margin: 0; }
.people.roles-row label.person { padding: 4px 10px; font-size: 13px; white-space: nowrap; }
/* The People page: the table across the whole width, the Add card under it (2026-10-01). They were
   side by side, the card a fixed 300px — and once the table grew a Two-factor column and an
   invitation's buttons it was wider than what was left, ran UNDER the card, and hid every row's
   buttons (Clint's screenshot of the live server). One column cannot be outgrown by a long email.
   The table scrolls inside its own box if it is ever wider than the page, rather than sliding
   beneath anything. */
.people-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; }
.people-grid > .card { max-width: 560px; }
.table-scroll { overflow-x: auto; }
td.people-actions { min-width: 150px; }
td.people-actions form.inline { display: block; margin: 0 0 6px; }
td.people-actions form.inline:last-child { margin-bottom: 0; }
td.people-actions .btn { width: 100%; white-space: nowrap; }
.people-grid .pill { white-space: nowrap; }

/* ---- office chat (stage 3.8.1, 2026-09-30): wwwroot/chat.js. A button in the corner of every
   portal page, the people in a list above it, and up to three conversations docked beside it. ---- */
.chat-launcher { position: fixed; right: 16px; bottom: 16px; z-index: 40; display: flex; align-items: center; gap: 8px;
  background: var(--fill); color: #fff; border: 0; border-radius: 999px; padding: 11px 18px; font: inherit; font-weight: 800;
  cursor: pointer; box-shadow: 0 10px 24px rgba(0, 0, 0, .28); }
/* A fixed deep red: --bad is a pale pink in the dark palette, and this carries white text. */
.chat-launcher.has-unread { background: #b91c1c; }
.chat-icon { font-size: 18px; line-height: 1; }
.chat-badge { display: inline-block; min-width: 20px; padding: 1px 6px; border-radius: 999px; background: #fff; color: #111;
  font-size: 12px; font-weight: 800; text-align: center; }
.chat-panel { position: fixed; right: 16px; bottom: 72px; z-index: 41; width: 300px; max-width: calc(100vw - 32px); max-height: min(60vh, calc(100vh - 110px));
  display: flex; flex-direction: column; background: var(--card); color: var(--ink); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: 0 18px 40px rgba(0, 0, 0, .35); overflow: hidden; }
.chat-panel[hidden] { display: none; }
.chat-panel-h { padding: 12px 14px 4px; font-weight: 800; }
.chat-search { margin: 6px 12px 8px; padding: 9px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--solid); color: var(--ink); font: inherit; }
.chat-list { overflow-y: auto; padding: 0 6px 8px; }
.chat-row { display: block; width: 100%; text-align: left; background: none; border: 0; color: var(--ink); font: inherit;
  padding: 8px 10px; border-radius: 10px; cursor: pointer; }
.chat-row:hover, .chat-row:focus-visible { background: var(--mist); }
.chat-row-top { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.chat-row .chat-badge { background: var(--fill); color: #fff; }
.chat-row-last { color: var(--muted); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-empty { color: var(--muted); font-size: 13px; padding: 6px 10px; margin: 0; }
.chat-dock { position: fixed; right: 16px; bottom: 72px; z-index: 39; display: flex; flex-direction: row-reverse; align-items: flex-end;
  gap: 12px; pointer-events: none; }
.chat-win { pointer-events: auto; width: 320px; height: min(420px, calc(100vh - 110px)); display: flex; flex-direction: column; background: var(--card);
  color: var(--ink); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 18px 40px rgba(0, 0, 0, .35); overflow: hidden; }
.chat-win.has-unread .chat-win-h { background: var(--fill); color: #fff; }
.chat-win-h { display: flex; justify-content: space-between; align-items: center; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.chat-x { background: none; border: 0; color: inherit; font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
.chat-msgs { flex: 1; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.chat-msg { max-width: 85%; align-self: flex-start; background: var(--mist); border-radius: 12px; padding: 6px 10px; }
.chat-msg.mine { align-self: flex-end; background: rgba(109, 40, 217, .18); }
.chat-meta { font-size: 11px; color: var(--muted); }
.chat-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.chat-err { color: var(--bad, #dc2626); font-size: 13px; padding: 0 12px; }
.chat-form { position: relative; display: flex; gap: 8px; align-items: flex-end; padding: 8px 10px 10px; border-top: 1px solid var(--line); }
.chat-input { flex: 1; resize: none; max-height: min(150px, 30vh); padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--solid); color: var(--ink); font: inherit; }
.chat-sug { position: absolute; left: 10px; bottom: 100%; margin-bottom: 4px; background: var(--card); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 8px 20px rgba(0, 0, 0, .3); padding: 4px; min-width: 180px; }
.chat-sug[hidden] { display: none; }
.chat-sug-row { display: block; width: 100%; text-align: left; background: none; border: 0; color: var(--ink); font: inherit; padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.chat-sug-row:hover { background: var(--mist); }
/* Website chat (3.8.3): a visitor to the company's own website, in the same corner. Amber, not red:
   somebody is waiting to be answered, which is different from "you have unread messages". #b45309
   carries white text at 5:1. */
.chat-launcher.has-visitor { background: #b45309; }
.chat-section { padding: 8px 14px 2px; font-size: 12px; font-weight: 800; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.chat-row.visitor .chat-row-top strong::before { content: "🌐 "; }
.chat-state { font-size: 12px; color: var(--muted); font-weight: 600; white-space: nowrap; }
.chat-state.waiting { color: #fff; background: #b45309; border-radius: 999px; padding: 1px 8px; }
.chat-win.visitor .chat-win-h { flex-wrap: wrap; }
.chat-sub { width: 100%; font-size: 12px; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
.chat-win.visitor.has-unread .chat-sub { color: #fff; }
.chat-tools { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 10px 0; }
.chat-tools button { font: inherit; font-size: 12px; font-weight: 700; padding: 4px 9px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--solid); color: var(--ink); cursor: pointer; }
.chat-tools button:hover { background: var(--mist); }
/* Hand over (2026-10-15): who to give the chat to, under its tools; and the note a hand-over leaves. */
.chat-handover { width: 100%; display: flex; gap: 6px; align-items: center; font-size: 12px; color: var(--muted); }
.chat-handover[hidden] { display: none; }
.chat-handover select { flex: 1; min-width: 0; font: inherit; font-size: 13px; padding: 4px 6px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--solid); color: var(--ink); }
.chat-tools .chat-handover .btn-accent { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); color: #fff; border-color: transparent; }
.chat-tools button[hidden] { display: none; }
.chat-note { align-self: center; max-width: 95%; font-size: 12px; font-style: italic; color: var(--muted); text-align: center; }
/* The name given at a support request (2026-10-18): only what they typed, so italic and muted — <em> alone is upright here. */
.requested-by { font-style: italic; color: var(--muted); }
/* The billing queue's pop-up (2026-10-05): top right, clear of the chat corner, amber like a website
   visitor — somebody's work is waiting — and it stays until it is closed or opened. */
.bill-pops { position: fixed; top: 16px; right: 16px; z-index: 45; display: flex; flex-direction: column; gap: 10px;
  width: 340px; max-width: calc(100vw - 32px); pointer-events: none; }
.bill-pop { pointer-events: auto; background: var(--card); color: var(--ink); border: 1px solid var(--line); border-left: 6px solid #b45309;
  border-radius: 14px; box-shadow: 0 18px 40px rgba(0, 0, 0, .35); padding: 10px 14px 12px; }
.bill-pop-h { display: flex; justify-content: space-between; align-items: center; font-size: 12px; font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; }
.bill-pop-t { font-weight: 800; margin: 2px 0; overflow-wrap: anywhere; }
.bill-pop-s { font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.bill-pop-a { margin-top: 10px; }
.chat-text a { color: inherit; text-decoration: underline; }
@media (max-width: 700px) {
  .chat-dock { left: 16px; right: 16px; flex-direction: column; align-items: stretch; }
  .chat-win { width: 100%; height: 60vh; }
  .chat-win:not(:last-child) { display: none; }   /* the newest, on a phone */
}

/* ---------- the client picker (wwwroot/clientpick.js, 2026-10-02) ----------
   A search box that narrows as you type, in place of a dropdown of every client. Rows are a
   finger high so it works the same on a phone. */
.cpick { position: relative; display: inline-block; min-width: 200px; flex: 1 1 220px; max-width: 100%; vertical-align: middle; }
.cpick-in { width: 100%; padding: 8px 10px; border: 1px solid var(--edge); border-radius: 10px; background: var(--panel-hi); color: var(--ink); font: inherit; }
.cpick-list { position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 4px); min-width: 240px; max-height: min(320px, 50vh); overflow-y: auto;
  background: var(--solid); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--sh-card); padding: 4px; text-align: left; }
.cpick-row { display: block; width: 100%; min-height: 40px; text-align: left; font: inherit; font-size: 14px; color: var(--ink); background: none;
  border: 0; border-radius: 8px; padding: 8px 10px; cursor: pointer; overflow-wrap: anywhere; }
.cpick-row.sub { padding-left: 26px; color: var(--muted); }
.cpick-row:hover, .cpick-row.on { background: var(--lift-hi); color: var(--ink); }
.cpick-note { padding: 8px 10px; font-size: 13px; color: var(--muted); }
.cpick-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 0; }

/* ---------- the portal on a phone (2026-10-02) ----------
   Clint: "If a technician logs into the dashboard via their cellphone, tickets and workflows must
   work flawlessly almost as if they are working from an app." Measured at 375px before this: a
   sticky header 245px tall (a quarter of the screen, on every page, all the way down), the ticket
   list a 853px table swiped sideways, its filters filling the whole first screen, every field
   under 16px (an iPhone zooms the page on each tap), and the Chat button over the content. */
.menu-btn { display: none; }
@media (max-width: 700px) {
  .wrap { padding: 0 16px; }
  /* One line of header: the brand and a Menu button. The links fold behind it. */
  .top .nav { flex-direction: row; flex-wrap: wrap; min-height: 56px; padding: 8px 0; gap: 8px; }
  .top .brand { font-size: 14px; gap: 8px; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .top .brand-logo { height: 28px; }
  .menu-btn { display: inline-flex; align-items: center; gap: 6px; font: inherit; font-weight: 800; font-size: 15px; color: var(--ink);
    background: var(--lift-hi); border: 1px solid var(--line); border-radius: 12px; padding: 8px 14px; min-height: 40px; cursor: pointer; }
  .menu-badge { background: #b45309; color: #fff; border-radius: 999px; font-size: 12px; padding: 1px 7px; }
  .top nav { display: none; width: 100%; flex-direction: column; align-items: stretch; gap: 0; padding: 4px 0 8px; }
  /* Scrolls inside itself (Clint, 2026-10-28: "I cannot scroll down to this on my phone, it stops at items"): the header is
     sticky, so a menu taller than the screen — the owner's and a supervisor's — had a bottom no finger could reach. */
  /* justify-content: flex-start — the narrow-screen rule CENTRES the menu, and a centred column that overflows pushes its first items
     above the top where nothing scrolls to them: Clint's menu began at Clients, with Dashboard, Connect, Branding … unreachable. */
  .top.open nav { display: flex; flex-wrap: nowrap; justify-content: flex-start; max-height: calc(100vh - 72px); max-height: calc(100dvh - 72px); overflow-y: auto;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  /* One column that scrolls — never squeezed, never wrapped into a second column off the side (the tabs' desktop rule). */
  .top.open nav > * { flex-shrink: 0; }
  .top nav > a, .top nav > form > a, .top nav > form > button { display: block; padding: 12px 4px; border-top: 1px solid var(--line); font-size: 16px; }
  .top nav > a.pill { margin: 6px 0 !important; text-align: center; }
  .top nav .theme-toggle { width: 100%; margin-top: 8px; }
  /* The menu's tabs, folded into a list: full-width rounded rows a thumb finds, the page you are on filled. */
  .top nav.tabs { gap: 6px; }
  .top nav.tabs > a:not(.pill), .top nav.tabs > form > a { display: block; padding: 11px 14px; border-radius: 12px; font-size: 16px; }
  .top nav.tabs > a.pill { margin: 0 !important; }

  /* Fields at 16px: below that an iPhone zooms the whole page in on every tap. */
  input:not([type=checkbox]):not([type=radio]), select, textarea { font-size: 16px !important; max-width: 100%; min-width: 0; }

  section.portal h1 { font-size: 26px; }
  .card { padding: 16px; border-radius: 18px; }
  .tintro { font-size: 14px; margin: 6px 0 12px; }
  .tstats { display: none !important; }   /* office totals; on a phone the next job matters more */
  .stats { gap: 8px; margin-bottom: 14px; }
  .stat { padding: 12px; border-radius: 16px; }
  .stat .n { font-size: 24px; }
  .stat .l { font-size: 12px; }

  /* Room under the last thing on a page for the Chat button, which floats over it. */
  body.section-portal main { padding-bottom: 76px; }
  .chat-launcher { padding: 10px 14px; right: 12px; bottom: 12px; }

  /* Lists: each row a card of label / value lines (wwwroot/phone.js labels the cells). */
  table.cards, table.cards tbody, table.cards tr, table.cards td { display: block; width: 100%; }
  table.cards { border-radius: 16px; }
  table.cards tr.cards-head { display: none; }
  table.cards tr { padding: 10px 14px; border-bottom: 1px solid var(--line); }
  table.cards tr:last-child { border-bottom: 0; }
  /* The label on the left; the value (phone.js wraps it in .cell-v) beside it, flowing as it would in the cell. */
  table.cards td { border: 0; padding: 5px 0; overflow-wrap: break-word; }
  table.cards td[data-label] { display: flex; gap: 10px; align-items: baseline; }
  table.cards td[data-label]::before { content: attr(data-label); flex: 0 0 35%; color: var(--muted); font-weight: 700; font-size: 13px; }
  table.cards .cell-v { flex: 1; min-width: 0; }
  table.cards td:not([data-label]) { padding-top: 8px; }
  table.cards .pill { white-space: nowrap; }
  table.cards .cpick, table.cards .cpick-form { min-width: 0; width: 100%; }
  .cpick { min-width: 0; }
  .cpick-list { min-width: 0; }   /* as wide as its box, never off the edge of the screen */
  table.cards td form.inline { display: inline-block; margin: 2px 4px 2px 0; }

  /* The ticket list: one card per job, tapped anywhere to open. */
  table.tlist, table.tlist tbody { display: block; }
  table.tlist tr:first-child { display: none; }
  table.tlist tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; padding: 12px 14px; border-bottom: 1px solid var(--line); position: relative; }
  table.tlist tr:last-child { border-bottom: 0; }
  table.tlist td { display: block; border: 0; padding: 0; font-size: 13px; }
  table.tlist .t-num { order: 1; }
  table.tlist .t-num br, table.tlist .t-status br { display: none; }
  table.tlist .t-subj { order: 2; flex: 1 1 60%; font-size: 15px; font-weight: 700; }
  table.tlist .t-status { order: 3; flex-basis: 100%; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  table.tlist .t-type { order: 4; }
  table.tlist .t-client { order: 5; color: var(--muted); font-weight: 700; }   /* the date-sorted list (2026-10-13) */
  table.tlist .t-client.none { display: none; }
  table.tlist .t-who { order: 5; color: var(--muted); }
  table.tlist .t-mach { order: 6; color: var(--muted); }
  table.tlist .t-mach:empty { display: none; }
  table.tlist .t-opened { order: 7; color: var(--muted); }
  table.tlist .t-time { order: 8; color: var(--muted); }
  table.tlist .t-time.none { display: none; }
  table.tlist .t-prio { order: 7; color: var(--muted); }
  table.tlist .t-upd { order: 7; color: var(--muted); }
  table.tlist .t-due { order: 7; }
  table.tlist .t-due:has(> .muted:only-child) { display: none; }
  table.tlist .t-go { position: static; }
  table.tlist .t-go a { position: absolute; inset: 0; opacity: 0; }   /* the whole card is the link */
  details.card > summary { padding: 2px 0; }
  details.card:has(table.tlist) { padding: 12px; }

  /* The filter: Show and Search on the first screen; the dates behind "Dates". */
  .tfilter > div { gap: 8px !important; }
  .tfilter > div > div { flex: 1 1 100% !important; min-width: 0 !important; }
  .tfilter select { width: 100%; }
  .tfilter .t-date { display: none; flex: 1 1 45% !important; }
  .tfilter.dates-on .t-date { display: block; }
  .tfilter .t-date input { width: 100%; }
  .tfilter .btn { flex: 1; }
}
.t-dates-btn { display: none; }
@media (max-width: 700px) { .t-dates-btn { display: inline-flex; justify-content: center; } }

/* ---- the knowledge base (3.8.5) ----
   An article is read like a page of instructions: a comfortable measure, numbered steps that stand
   out, commands in a block that keeps its spacing, screenshots at full width of the column. Every
   colour is a token, so both palettes come for free. */
.kb-list { display: grid; gap: 10px; }
.kb-item { display: block; padding: 14px 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--card); color: var(--ink); }
.kb-item:hover { border-color: rgba(var(--grape-rgb), .45); background: var(--lift); color: var(--ink); }
.kb-item .kb-t { font-weight: 800; font-size: 16px; color: var(--grape); }
.kb-item .kb-s { color: var(--muted); font-size: 14px; font-weight: 500; margin-top: 2px; overflow-wrap: anywhere; }
.kb-item .kb-m { color: var(--muted); font-size: 12px; font-weight: 600; margin-top: 4px; }
.kb-client { margin: 26px 0 10px; font-size: 18px; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.kb-client a { font-size: 13px; }
.kb-body { max-width: 860px; font-size: 16px; line-height: 1.65; overflow-wrap: anywhere; }
.kb-body h2 { font-size: 21px; margin: 26px 0 8px; }
.kb-body h3 { font-size: 18px; margin: 20px 0 6px; }
.kb-body h4 { font-size: 16px; margin: 16px 0 4px; }
.kb-body p { margin: 0 0 12px; }
.kb-body ol, .kb-body ul { margin: 0 0 14px; padding-left: 28px; }
.kb-body ol > li { margin: 6px 0; padding-left: 4px; }
.kb-body ol > li::marker { font-weight: 900; color: var(--grape); }
.kb-body pre { background: var(--lift); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; overflow-x: auto; margin: 0 0 14px; }
.kb-body pre code { background: none; border: 0; padding: 0; color: var(--ink); font-size: 14px; white-space: pre; }
.kb-fig { margin: 10px 0 16px; }
.kb-fig img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 10px; }
.kb-tools { display: flex; gap: 6px; flex-wrap: wrap; margin: 8px 0 6px; }
.kb-edit textarea#kbBody { min-height: 420px; font-family: Consolas, "Cascadia Mono", monospace; font-size: 14px; line-height: 1.55; }
.kb-edit textarea#kbBody.drop { border-color: var(--grape); box-shadow: 0 0 0 4px rgba(var(--grape-rgb), .22); }
.kb-edit .form, form.kb-edit { max-width: 900px; }
/* The client picker is inline for table rows; here it is a field of the form, the full line like the rest. */
.kb-edit .cpick { display: block; }
.kb-edit .cpick-in { padding: 13px 15px; }
.kb-preview { border: 1px dashed var(--line); border-radius: 14px; padding: 16px 18px; margin-top: 10px; min-height: 120px; }
.kb-note { font-size: 13px; color: var(--muted); margin: 6px 0 0; }
.kb-ticket { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; margin: 10px 0; font-size: 14px; }
.kb-ticket .kb-ref { font-weight: 700; }
/* Link buttons (2026-10-06): an address as a button with words on it, never a long line of address. */
.kb-btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; margin: 2px 0; border-radius: 999px; border: 1px solid rgba(var(--grape-rgb), .45);
  background: rgba(var(--grape-rgb), .10); color: var(--grape); font-weight: 800; font-size: 15px; line-height: 1.3; text-decoration: none; max-width: 100%; overflow-wrap: anywhere; }
.kb-btn:hover { background: rgba(var(--grape-rgb), .2); color: var(--grape); text-decoration: none; }
.kb-btn-line { margin: 4px 0 14px; }
/* Folders (2026-10-06): opened like a folder on a PC, with the way back above. */
.kb-new { float: right; }
/* A <nav>, so the site's own nav rules (centred on a phone, the menu's colours) are put back here. */
.kb-crumbs, nav.kb-crumbs { display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: flex-start; align-items: baseline; margin: 0 0 14px; font-size: 15px; }
nav.kb-crumbs a { color: var(--grape); font-weight: 700; }
.kb-crumbs > span[aria-hidden] { color: var(--muted); }
.kb-crumbs .kb-crumb-side { margin-left: auto; font-size: 13px; }
.kb-folders { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; margin: 0 0 12px; }
.kb-folder { display: flex; gap: 10px; align-items: center; padding: 12px 16px; border: 1px solid var(--line); border-radius: 14px; background: var(--lift); color: var(--ink); min-width: 0; }
.kb-folder:hover { border-color: rgba(var(--grape-rgb), .45); background: var(--card); color: var(--ink); }
.kb-folder .kb-fi { font-size: 22px; line-height: 1; }
.kb-folder .kb-t { display: block; font-weight: 800; font-size: 15px; color: var(--grape); overflow-wrap: anywhere; }
.kb-folder .kb-m { display: block; color: var(--muted); font-size: 12px; font-weight: 600; }
.kb-folder-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; margin: 0 0 14px; }
.kb-tool > summary { list-style: none; cursor: pointer; }
.kb-tool > summary::-webkit-details-marker { display: none; }
.kb-tool[open] { flex-basis: 100%; }
.kb-inline { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
.kb-inline input, .kb-inline select { padding: 9px 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); color: var(--ink); min-width: 0; }
.kb-inline input { flex: 1 1 220px; }
.kb-inline select { max-width: 100%; }
@media (max-width: 700px) {
  .kb-folders { grid-template-columns: 1fr; }
  /* On a phone the button has its own line under the heading, never over the way back. */
  .kb-new { float: none; display: flex; width: fit-content; margin-top: 10px; }
  .kb-inline input, .kb-inline select { font-size: 16px; }
  .kb-body { font-size: 16px; }
  .kb-edit textarea#kbBody { min-height: 300px; font-size: 16px; }
  .kb-tools .btn { flex: 1 1 30%; justify-content: center; }
}

/* Files and photos on a comment (2026-10-13): picked ones as chips with ×, posted ones as pictures and links. */
.att{margin:6px 0 10px}
.att-pick{display:inline-block;cursor:pointer;position:relative}
.att-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.att-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 6px 4px 10px;border:1px solid var(--line);border-radius:999px;font-size:13px;background:var(--card);max-width:100%;overflow-wrap:anywhere}
.att-x{border:none;background:none;color:var(--muted);font-size:16px;line-height:1;cursor:pointer;padding:0 4px}
.att-x:hover{color:var(--bad)}
.att-note.att-bad{color:var(--bad)}
.att-shown{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.att-shown img{width:150px;height:112px;object-fit:cover;border-radius:10px;border:1px solid var(--line);display:block}
/* A step gone back over (2026-10-13): still in the story, plainly not counting. */
.tk-undone{opacity:.6}
.tk-undone .tk-body{text-decoration:line-through;text-decoration-thickness:1px}
.tk-undone-note{font-size:12px;color:var(--warn,#b45309);font-weight:700;margin-top:6px}
.tk-warn{background:rgba(245,158,11,.14);border:1px solid rgba(245,158,11,.45);border-radius:10px;padding:8px 12px;font-size:14px;margin:6px 0 10px}

/* The control dashboard (2026-10-13): one card per server, a meter per reading, its level as a dot. */
.servers{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(380px,100%),1fr));gap:20px;margin-bottom:28px}
.server-card h2{margin:0;font-size:22px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.server-card .spec{color:var(--muted);font-size:13px;margin:6px 0 14px;overflow-wrap:anywhere}
.meter{margin:9px 0}
.meter .mrow{display:flex;justify-content:space-between;gap:10px;font-size:13px;font-weight:700}
.meter .mrow .d{color:var(--muted);font-weight:400;text-align:right}
.meter .bar{height:8px;border-radius:4px;background:var(--lift-hi);overflow:hidden;margin-top:4px}
.meter .bar>i{display:block;height:100%;background:var(--ok)}
.meter.amber .bar>i{background:var(--warn)}
.meter.red .bar>i{background:var(--bad)}
.dot{width:12px;height:12px;border-radius:50%;display:inline-block;background:var(--ok);flex:none}
.dot.amber{background:var(--warn)}
.dot.red,.dot.down{background:var(--bad)}
.server-counts{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin:14px 0;text-align:center}
.server-counts b{display:block;font-size:22px}
.server-counts span{color:var(--muted);font-size:12px}
.advice{font-size:14px;padding:10px 12px;border-radius:12px;background:var(--lift)}
.advice.amber{background:rgba(245,158,11,.14)}
.advice.red,.advice.down{background:rgba(239,68,68,.14)}
.server-group{margin:30px 0 10px;display:flex;align-items:center;gap:10px}

/* ---- The public site (2026-10-14, stage E) ---------------------------------------------------------------------------
   A footer with every page in it, and the pieces the feature pages share. */
.foot-site .foot-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; align-items: start; }
.foot-site h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .06em; margin: 0 0 10px; color: var(--ink); }
.foot-site .foot-cols a { display: block; padding: 3px 0; }
.foot-site .foot-legal { display: block; margin-top: 22px; font-size: 13px; font-weight: 500; }
.lede { font-size: 19px; color: var(--muted); max-width: 760px; }
.page-head { padding: 64px 0 18px; }
.page-head h1 { font-size: 40px; line-height: 1.15; margin: 0 0 14px; }
.facts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }
.fact h3 { margin-top: 0; }
.usp { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.usp .card h3 { margin-top: 0; }
.next-links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }
.calc { display: grid; grid-template-columns: auto 1fr; gap: 10px 16px; align-items: center; max-width: 520px; }
.calc input[type=range] { width: 100%; }
.calc .total { font-size: 30px; font-weight: 900; }
@media (max-width: 900px) {
  .foot-site .foot-cols, .usp, .facts { grid-template-columns: 1fr; }
  .page-head h1 { font-size: 32px; }
}
/* The region buttons on a phone (2026-10-14): four in a row ran off the screen and cut "Europe" off — two rows instead. */
@media (max-width: 700px) {
  .toggle { display: grid; grid-template-columns: 1fr 1fr; border-radius: 22px; max-width: 100%; }
  .toggle button { padding: 9px 10px; }
}

/* Reviews (2026-10-14): the star picker — radios in reverse so a star and those left of it light up — and stars shown. */
.stars-pick { display: inline-flex; flex-direction: row-reverse; gap: 4px; }
.stars-pick input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.stars-pick label { font-size: 34px; line-height: 1; color: var(--line); cursor: pointer; margin: 0; }
.stars-pick input:checked ~ label, .stars-pick label:hover, .stars-pick label:hover ~ label { color: #f5b301; }
.stars-pick input:focus-visible + label { outline: 2px solid var(--fill); border-radius: 6px; }
.review-stars { color: #f5b301; letter-spacing: 2px; font-size: 18px; }
.review-card blockquote { margin: 10px 0 12px; font-size: 16px; }

/* ─────────────────────────────────────────────────────────────────────────────
   SCREENSHOTS — 2026-10-14. Clint: "add some screenshots so that people can get a good look and feel." Every picture
   is in wwwroot/shots twice, made by tools/siteshots from the real windows in the light and the dark theme; the page shows
   the one it is in (its own light or dark — the website switch, or the visitor's computer). _Shot.cshtml draws one. */
:root:not([data-theme="light"]) .shot-light,
:root[data-theme="light"] .shot-dark { display: none; }
.shot-frame { display: block; border-radius: 14px; overflow: hidden; border: 1px solid var(--line); background: var(--card);
  box-shadow: var(--sh-hero); cursor: zoom-in; transition: transform .15s ease, box-shadow .15s ease; }
.shot-frame:hover { transform: translateY(-2px); box-shadow: var(--sh-hover), var(--sh-hero); }
.shot-frame img { display: block; width: 100%; height: auto; }
.shot-figure { margin: 0; }
.shot-figure figcaption { color: var(--muted); font-size: 15px; margin-top: 12px; text-align: center; }
.shot-wide { max-width: 1060px; margin: 0 auto; }
.shot-mid { max-width: 760px; margin: 0 auto; }
/* The customer's three small windows, side by side and lined up at the top. */
.shot-row { display: grid; grid-template-columns: 438fr 520fr 540fr; gap: 22px; align-items: start; max-width: 980px; margin: 0 auto; }

/* The home page's picture: the console, with the customer's app in front of its corner. */
.hero-shots { position: relative; padding: 0 0 34px 34px; }
.hero-shots .hero-float { position: absolute; left: 0; bottom: 0; width: 30%; }
.hero-shots .hero-float .shot-frame { box-shadow: var(--sh-hover), var(--sh-hero); }

/* The tour: one picture at a time, chosen by its tab. Without a script the tabs stay hidden and every picture shows. */
.tour-tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 26px 0 24px; }
.tour-tabs[hidden] { display: none; }
.tour-tabs button { font: inherit; font-size: 15px; font-weight: 800; color: var(--ink); background: var(--lift); border: 1px solid var(--edge);
  border-radius: 999px; padding: 9px 18px; cursor: pointer; }
.tour-tabs button:hover { border-color: rgba(var(--grape-rgb), .45); color: var(--grape); }
.tour-tabs button[aria-selected="true"] { background: linear-gradient(135deg, var(--fill), var(--fill-lite)); border-color: transparent; color: #fff; }
.tour-pane + .tour-pane { margin-top: 40px; }
.tour.ready .tour-pane + .tour-pane { margin-top: 0; }
.tour-pane h3 { text-align: center; margin: 18px 0 6px; }
.tour-pane p { text-align: center; color: var(--muted); max-width: 720px; margin: 0 auto; }

/* A picture full size, over the page. */
.shot-view { border: 0; padding: 0; background: transparent; max-width: 96vw; max-height: 94vh; overflow: visible; }
.shot-view::backdrop { background: rgba(5, 8, 12, .84); }
.shot-view img { display: block; max-width: 96vw; max-height: 94vh; width: auto; height: auto; border-radius: 12px; cursor: zoom-out; }
.shot-view .shot-close { position: absolute; top: -14px; right: -14px; width: 36px; height: 36px; border-radius: 50%; border: 0;
  background: #fff; color: #111; font: inherit; font-size: 18px; font-weight: 900; cursor: pointer; box-shadow: 0 6px 18px rgba(0, 0, 0, .4); }

@media (max-width: 900px) {
  .hero-shots { padding: 0 0 24px 18px; }
  .shot-row { grid-template-columns: 1fr 1fr; }
  .shot-row > :last-child { grid-column: 1 / -1; max-width: 360px; justify-self: center; }
}

/* ---------- the @ list in a ticket's comment box (2026-10-21, mentionpick.js) ---------- */
.mention-pick {
  display: none; position: absolute; z-index: 1000; min-width: 220px; max-width: 320px; max-height: 280px;
  overflow-y: auto; padding: 4px; background: var(--card); color: var(--ink);
  border: 1px solid var(--edge); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
}
.mention-pick .mp-h {
  padding: 7px 10px 3px; font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.mention-pick .mp-h + .mp-i { margin-top: 1px; }
.mention-pick .mp-i { padding: 8px 10px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mention-pick .mp-i.on { background: rgba(var(--grape-rgb), .16); color: var(--grape); }

/* Latest activity (2026-10-26, HANDOVER §164) opens a ticket AT an entry of its story: that entry is marked, below the header. */
[id^="note-"] { scroll-margin-top: 90px; }
[id^="note-"]:target { box-shadow: 0 0 0 2px var(--grape); }

/* The ticket list's headings sort (2026-10-26, HANDOVER §165): each a link, the one in use with its arrow. On a phone the
   headings fold away with the table, and a small Sort box stands in for them. */
table.tlist th a.t-sort { color: inherit; text-decoration: none; }   /* "Assigned to" and "Last updated" may wrap: eleven columns must fit a laptop */
table.tlist th a.t-sort span { white-space: nowrap; }
/* Never the page sideways: a list too wide for its card scrolls inside it (measured at 1024 px, 2026-10-26). */
.card:has(> table.tlist) { overflow-x: auto; }
/* Eleven columns: the cells closer together than an ordinary table's 18 px, so the list fits a 1024 px window (measured). */
@media (min-width: 701px) { table.tlist th, table.tlist td { padding-left: 10px; padding-right: 10px; } }
table.tlist th a.t-sort:hover { color: var(--grape); text-decoration: underline; }
table.tlist th a.t-sort.on { color: var(--grape); }
.t-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; }
.t-prio, .t-upd, .t-due { white-space: nowrap; }
.t-late { color: var(--bad, #dc2626); font-weight: 700; }
.pill.t-replied { background: #ea580c; color: #fff; }
.t-phone-sort { display: none; }
@media (max-width: 700px) {
  .t-phone-sort { display: block; margin: 0 0 10px; }
  .t-phone-sort label { display: flex; gap: 8px; align-items: center; font-weight: 800; font-size: 13px; }
  .t-phone-sort select { flex: 1; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; }
}
/* A reminder's pop-up (2026-11-03): the billing pop-up's card, in the accent colour — it is the person's own. */
.rem-pop { border-left-color: var(--accent); }
.rem-acts { display: flex; gap: 6px; flex-wrap: wrap; }
