/* ---------- The app's look, redesign round B (D-351) ----------
   The first part of the second sheet, scannlog-pages.css, so it reaches the subscriber's, public
   and admin pages and never the worker's pages, which load only scannlog.css (round D). It sets
   the approved design's tokens over the kit's (docs/design/DESIGN_HANDOFF.md, "Look"); every
   rule after it, and the kit's own classes, draw with them. No green: the kit's success tokens
   now hold the good status, blue on a blue tint, so a "success" badge or notice is blue. */

/* Archivo 700 and 800, version 2.001, the official files, unmodified (D-341): the headings of every
   page but the worker's. Inter stays the body font (D-222). */
@font-face { font-family: Archivo; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/Archivo-Bold.woff2?v=e289950dd907") format("woff2"); }
@font-face { font-family: Archivo; font-style: normal; font-weight: 800; font-display: swap; src: url("fonts/Archivo-ExtraBold.woff2?v=8cc0e60eef22") format("woff2"); }

:root {
  --navy: #172554;
  --on-navy: #cbd5e1;
  --on-navy-strong: #ffffff;
  --on-navy-accent: #93c5fd;
  --on-navy-muted: #94a3b8;
  --navy-line: rgba(148, 163, 184, 0.25);
  --page: #f3f4f6;
  --surface: #ffffff;
  --surface-sunk: #f9fafb;
  --border: #e5e7eb;
  --ink: #111827;
  --body: #4b5563;
  --muted: #646b78; /* 4.87:1 on the grey page, AA for small text (D-384) */
  --primary: #1e40af;
  --primary-hover: #1e3a8a;
  --link: #2563eb;
  --tint: #eff6ff;
  --success: #1e40af;
  --success-bg: #eff6ff;
  --warning: #b45309;
  --warning-bg: #fffbeb;
  --danger: #b91c1c;
  --danger-bg: #fef2f2;
  --danger-fill: #b91c1c;
  --accent: #1e40af;
  --white: #ffffff;
  --line-input: #d1d5db;
  --line-soft: #f3f4f6;
  --line-good: #bfdbfe;
  --line-warning: #fcd34d;
  --line-problem: #fecaca;
  --chip-ink: #374151;
  --track: #e5e7eb;
  --avatar-on-navy: #334155;
  --name-on-navy: #e2e8f0;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --shadow-card: 0 1px 2px rgba(17, 24, 39, 0.04);
  --shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.06);
  --font-display: Archivo, Inter, ui-sans-serif, system-ui, sans-serif;
  /* The phone's tab bar, and the room every page keeps under it (D-353). */
  --tabbar: 64px;
}

/* Headings in Archivo. A page title is 28 px on a phone and 32 px from 640 px (in pages.css). */
h1, h2, h3 { font-family: var(--font-display); letter-spacing: -0.01em; }
h1 { font-weight: 800; font-size: 28px; line-height: 36px; }
h2 { font-weight: 700; font-size: 20px; line-height: 28px; }
h3 { font-weight: 700; font-size: 17px; line-height: 24px; }
/* Small capitals over a heading: the day and the zone, a group of links. */
.eyebrow { margin: 0; font: 600 12px/16px var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }

/* Shapes: buttons 10 px, cards 16 px with a 1 px border and a light shadow, badges 6 px. */
.card { border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
.btn-secondary { border-color: var(--line-input); }
.btn-secondary:hover { background: var(--surface-sunk); }
.table-wrap { border-radius: var(--radius-lg); }
.table th { background: var(--surface-sunk); color: var(--muted); font-size: 12px; line-height: 16px; letter-spacing: 0.06em; text-transform: uppercase; }
.table td { border-bottom-color: var(--line-soft); }
/* A notice is a tinted panel; the good one is blue, never green. */
.notice { border-radius: var(--radius-md); }
.notice-success { background: var(--tint); border-color: var(--line-good); }
.notice-warning { border-color: var(--line-warning); }
.notice-danger { border-color: var(--line-problem); }

/* ---------- The public, admin and app pages' own frame (D-368) ----------
   Moved from layer.css, the first sheet, which every page loads, to the second sheet, which every
   page but the worker's loads: the public and admin header with its menu, the page column, the
   footer, the table box and the printed labels. The worker's sheet keeps only what its pages use. */

/* ---------- Header, with the narrow-screen menu (D-227) ---------- */
/* The subscriber's links are in the page twice: in a row, and in a <details> menu. One of the two is
   shown, by width alone, so the menu needs no script. */
.site-header { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); padding: var(--space-3) var(--space-4); background: var(--surface); border-bottom: 1px solid var(--border); }
.site-header .logo { margin-right: auto; }
.nav-row { display: none; flex-wrap: wrap; align-items: center; gap: 0 var(--space-3); }
/* Signed out: Pricing, Sign in and Create account stay on one row; the last is a small button, so
   it never wraps to a line of its own (D-250). The admin's longer row may still wrap. */
.nav-plain { display: flex; flex-wrap: nowrap; white-space: nowrap; align-items: center; gap: 0 var(--space-2); }
.admin-row { flex-wrap: wrap; white-space: normal; gap: 0 var(--space-3); }
.btn-small { min-height: 36px; padding: 6px 12px; font-size: 14px; line-height: 20px; }
.nav-plain .btn-small { margin-left: var(--space-1); padding: 6px 12px; color: var(--on-primary); }
.nav-plain .btn-small:hover { color: var(--on-primary); }
.nav-row a, .nav-plain a, .menu-links a { color: var(--ink); text-decoration: none; padding: var(--space-2) var(--space-1); }
.nav-row a:hover, .nav-plain a:hover, .menu-links a:hover { color: var(--link); }
.header-tools form, .nav-plain form { margin: 0; }
/* The uses (D-384): a <details> menu in the header, which needs no script; its list hangs under it. */
.nav-uses { position: relative; }
.nav-uses summary { display: inline-flex; align-items: center; min-height: 44px; padding: var(--space-2) var(--space-1); color: var(--ink); cursor: pointer; list-style: none; }
.nav-uses summary::-webkit-details-marker { display: none; }
.nav-uses summary::after { content: "\25BE"; margin-left: 4px; font-size: 12px; }
.nav-uses-panel { position: absolute; left: 0; top: 100%; z-index: 10; display: grid; min-width: 220px; padding: var(--space-2); background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-card); white-space: normal; }
.nav-uses-panel a { display: flex; align-items: center; min-height: 44px; }
/* On a phone the uses, Pricing, About and signing in no longer fit on one line: the links wrap,
   flush right, and the menu's list opens from the right edge so it stays on the screen (D-384). */
@media (max-width: 640px) {
  .nav-plain { flex-wrap: wrap; justify-content: flex-end; white-space: normal; gap: 0 var(--space-1); }
  .nav-uses-panel { left: auto; right: 0; }
}
/* The account's name, sign-out and the languages: one group, so the header's wrapping can never
   part them. On a phone it is the line under the logo and the Menu button (D-237). */
.header-tools { order: 3; flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--space-3); }
.account-name { max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: 14px; }
/* The Menu button keeps its place when opened: the list hangs under the whole header (D-238). */
.menu { order: 2; }
.menu summary { list-style: none; cursor: pointer; }
.menu summary::-webkit-details-marker { display: none; }
.menu-links { position: absolute; top: 100%; left: 0; right: 0; z-index: 10; display: grid; padding: 0 var(--space-4) var(--space-2); background: var(--surface); border-bottom: 1px solid var(--border); box-shadow: var(--shadow-card); }
.menu-links a { display: flex; align-items: center; min-height: 44px; }
/* From 900 px the links are a row. Ten links, the account's name and sign-out do not fit beside the
   logo and the languages until about 1,450 px in French, so the row is a line of its own under
   them and wraps inside itself if it must: nothing is positioned, so nothing can overlap (D-233). */
@media (min-width: 900px) {
  .nav-row { display: flex; flex-basis: 100%; order: 5; padding-top: var(--space-2); border-top: 1px solid var(--border); }
  .header-tools { order: 2; flex-basis: auto; }
  .menu { display: none; }
}

/* ---------- Page column and footer ---------- */
.site-main { max-width: 1120px; margin: 0 auto; padding: var(--space-8) var(--space-4); }
.site-footer { max-width: 1120px; margin: 0 auto; padding: var(--space-6) var(--space-4); color: var(--muted); font-size: 14px; line-height: 20px; border-top: 1px solid var(--border); }
/* Every public page, in the page's language, so none is an orphan (D-384). */
.footer-links { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin-top: var(--space-3); }
.footer-links a { display: inline-flex; align-items: center; min-height: 32px; }
/* A table scrolls inside its own wrap, never the page (D-227, Q-051). */
.table-wrap { max-width: 100%; -webkit-overflow-scrolling: touch; }

/* ---------- Print: the label sheet ---------- */
/* Printed labels. Fixed cells in millimetres, sized to fit both Letter and A4 with a 10 mm
   page margin (printable area at least 190 x 259 mm). The quiet zone the QR standard needs
   is inside the code image itself, so it survives any cutting. Black ink, by design. */
.qr-preview svg, .label-code svg { display: block; width: 100%; height: auto; }
.page { margin-top: 24px; }
.page + .page { break-before: page; page-break-before: always; }
.labels { display: grid; gap: 4mm; justify-content: start; }
.labels-1 { grid-template-columns: 188mm; }
.labels-6 { grid-template-columns: repeat(2, 92mm); }
.labels-12 { grid-template-columns: repeat(3, 60mm); }
.label { position: relative; box-sizing: border-box; overflow: hidden; text-align: center; padding: 2mm; border: 0.2mm dashed #9aa3b2; break-inside: avoid; background: #fff; }
.labels-1 .label { height: 255mm; padding-top: 10mm; }
.labels-6 .label { height: 82mm; }
.labels-12 .label { height: 61mm; }
.label-code { margin: 0 auto; }
.labels-1 .label-code { width: 160mm; }
.labels-6 .label-code { width: 62mm; }
.labels-12 .label-code { width: 45mm; }
.label-name { margin: 2mm 0 0; font-weight: 700; color: #000; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.labels-1 .label-name { font-size: 24pt; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; }
.labels-6 .label-name { font-size: 11pt; }
.labels-12 .label-name { font-size: 8pt; margin-top: 1mm; }
.label-line, .label-url { margin: 1mm 0 0; color: #000; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.labels-1 .label-line, .labels-1 .label-url { font-size: 14pt; }
.labels-6 .label-line, .labels-6 .label-url { font-size: 8pt; padding: 0 9mm; }
.labels-12 .label-line, .labels-12 .label-url { font-size: 6.5pt; margin-top: 0.5mm; }
.label-url { font-family: ui-monospace, Menlo, Consolas, monospace; }
/* The page's fixed 24 px line height pushed the address off the foot of the medium and the small
   label; a label's lines are spaced by their own size (D-402). */
.label p { line-height: 1.25; }
/* The black mark at the foot of the large and the medium label, never the small one (D-235). It
   keeps a quarter of its height clear on every side and sits under the name, far from the code. */
.label-mark { position: absolute; display: block; width: auto; }
.labels-1 .label-mark { left: 50%; bottom: 8mm; height: 12mm; transform: translateX(-50%); }
.labels-6 .label-mark { left: 3mm; bottom: 3mm; height: 6mm; }
@page { margin: 10mm; }
@media print {
  .no-print { display: none !important; }
  body { background: #fff; }
  .site-main { max-width: none; padding: 0; margin: 0; }
  .page { margin-top: 0; }
  .label { border-color: #c8ced8; }
}

/* ScanNLog — the second stylesheet (D-243): the rules of the subscriber's, public and admin pages.
   Joined from app/styles/pages.css and app/styles/public.css by scripts/build_css.py into
   app/static/scannlog-pages.css. It is loaded after scannlog.css and uses its tokens; the worker's
   pages never load it. Written against the tokens only. */

/* ---------- The subscriber's, public and admin pages: what the kit does not have ---------- */
/* A page is one column of blocks. Long words (a link, an address) break instead of widening it. */
.view { display: grid; gap: var(--space-4); overflow-wrap: anywhere; }
.view > *, .view .card > *, .form > *, .group > * { min-width: 0; }
.view-narrow { max-width: 560px; width: 100%; margin: 0 auto; }
.view h2, .view h3 { margin: 0; }
.view > h2 { margin-top: var(--space-4); }
.view .card { display: grid; gap: var(--space-4); }
.site-main.admin { max-width: 1200px; }
.admin-word { font: 600 15px/22px var(--font-sans); color: var(--muted); margin-right: auto; }
/* The admin's tabs in the app's shell, with who is signed in to it and its own Sign out (D-376). */
.admin-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); }
.admin-bar .seg { margin-right: auto; }
.admin-bar form { margin: 0; }
.lead { font-size: 18px; line-height: 28px; color: var(--body); }
.hero h1 { font: 800 30px/38px var(--font-sans); }
/* A form is a column of fields, no wider than a line is comfortable to read. */
.form { display: grid; gap: var(--space-4); max-width: 560px; }
.group { display: grid; gap: var(--space-3); border: 0; padding: 0; margin: 0; }
.group legend { font: 700 16px/24px var(--font-sans); color: var(--ink); padding: 0; margin-bottom: var(--space-2); }
.row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); }
.row .field { flex: 1 1 160px; }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); }
.actions form, .table form { margin: 0; }
.actions a[aria-current="true"] { font-weight: 600; color: var(--ink); }
/* A long label wraps inside its button or badge instead of running off a phone (D-236). */
.btn { max-width: 100%; }
.view .badge { white-space: normal; }
.field-help a, .meta a { color: var(--link); }
.list { display: grid; gap: var(--space-1); margin: 0; padding-left: 20px; color: var(--body); }
/* A small form inside a table cell: its control and its button side by side. */
.cell-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.cell-form .input { flex: 1 1 160px; width: auto; min-width: 160px; }
.table .thumb { display: block; width: 64px; height: 64px; object-fit: cover; border-radius: var(--radius-sm); }
.table .field { min-width: 200px; }
/* A table scrolls inside its wrap; it never squeezes (D-240). The page lets a long word break
   anywhere, and a table must not inherit that: a cell is one line unless it holds free text,
   which wraps at spaces and keeps a readable width. */
.table th, .table td { white-space: nowrap; overflow-wrap: normal; word-break: normal; }
.table td.text { white-space: normal; min-width: 220px; }
.table .badge { white-space: nowrap; }
.table td.text .badge { white-space: normal; }
.qr-preview { width: 180px; }
.map { height: 320px; border-radius: var(--radius-md); }
.suggestions { list-style: none; padding: 0; margin: 0; }
code { font-family: var(--font-mono); color: var(--ink); }
.join-code { font-size: 18px; letter-spacing: 1px; }
.join-link, .invite-link { word-break: break-all; }
/* Wide enough for a price on one line (D-249) with the card's padding, as on Billing (D-363). */
.plans { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(270px, 100%), 1fr)); gap: var(--space-4); }
.view .plan { gap: var(--space-2); align-content: start; }
.plan .price { font: 700 21px/28px var(--font-sans); color: var(--ink); white-space: nowrap; }
.plan .btn { margin-top: var(--space-2); }
/* ---------- The app shell (D-252, redrawn in D-352 and D-353) ---------- */
/* Below 1,024 px: a navy header with the logo, New point and Alerts, the page, and a tab bar fixed
   at the foot of the screen. From 1,024 px: a navy sidebar the height of the screen, and a white
   top bar with the search, the languages and New point over the page. */
.app-body { display: block; }
.app-column { min-width: 0; }
.app-column > .site-main { width: 100%; min-width: 0; }
.app-header { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: var(--space-3); min-height: 60px; padding: var(--space-2) var(--space-4); background: var(--navy); }
/* On a phone the buttons keep their one line and their size; the logo gives way (D-255). */
.app-header .logo { flex: 0 1 auto; min-width: 0; margin-right: auto; }
.app-header .btn { flex: none; white-space: nowrap; }
.app-header .btn-small { padding: 6px 10px; }
.app-header .logo img { height: 26px; }
/* The new lockup is 136 px wide at 26 px (D-350). Under 380 px it is 23 px high, 121 px wide, so
   it still fits beside "Nouveau point" and Alerts at 360 px. */
@media (max-width: 379px) { .app-header .logo img { height: 23px; } }
.app-header form { margin: 0; }
/* On navy, New point is a white button; from 1,024 px, on white, it is the primary one. */
.app-header .app-new { gap: 6px; background: var(--surface); color: var(--primary); }
.app-header .app-new .icon { display: none; }
.app-alerts { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: var(--radius-md); color: var(--on-navy-strong); }
.app-alerts:hover { background: rgba(255, 255, 255, 0.08); }
.app-alerts .chip { position: absolute; top: 2px; right: 0; }
.app-lang { display: none; }
.app-side { display: none; }
/* The links: one list, drawn in the sidebar and, without the tab bar's four, under More. */
.app-links { display: grid; gap: 2px; }
.app-links a { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; padding: 10px 12px; border-radius: 8px; color: var(--ink); font: 500 15px/22px var(--font-sans); text-decoration: none; }
.app-links a:hover { background: var(--tint); color: var(--primary); }
.app-links a.on { background: var(--tint); color: var(--primary); font-weight: 600; }
.app-links .icon, .app-tab .icon { flex: none; }
.app-link-label { flex: 1 1 auto; min-width: 0; }
.app-group { margin: 14px 12px 4px; font: 600 11px/16px var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
/* A count that is waiting for the subscriber, white on the problem red. Never drawn at zero. */
.chip { flex: none; min-width: 20px; margin-left: auto; padding: 0 6px; border-radius: var(--radius-pill); background: var(--danger); color: var(--white); font: 700 12px/20px var(--font-sans); text-align: center; font-variant-numeric: tabular-nums; }
.account { display: flex; align-items: center; gap: 10px; min-width: 0; }
.account-initials { flex: none; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 8px; background: var(--primary); color: var(--white); font: 700 13px/18px var(--font-sans); }
.account-text { display: grid; min-width: 0; }
.account .account-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font: 600 14px/18px var(--font-sans); }
.account-plan { color: var(--muted); font-size: 12px; line-height: 18px; }
/* More codes than the plan allows: the line is in the warning colour and the block leads to Billing. */
.account-over { text-decoration: none; }
.account-over .account-plan { color: var(--warning); font-weight: 600; }

/* The phone's tab bar (D-353): four pages and More. Each tab is as wide as its longest word and
   the five share the rest, so "Seguimientos" fits at 360 px; a label may take two lines. */
.app-tabbar { display: none; }
.app-tab { position: relative; flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 0; min-height: 44px; padding: 6px 4px; border-radius: 8px; color: var(--muted); font: 600 12px/14px var(--font-sans); text-align: center; text-decoration: none; list-style: none; cursor: pointer; }
.app-tab::-webkit-details-marker { display: none; }
.app-tab:hover { color: var(--ink); }
.app-tab[aria-current="page"], .app-more[open] > .app-tab { color: var(--primary); }
.app-tab .chip { position: absolute; top: 0; left: calc(50% + 4px); margin: 0; }
.app-more { flex: 1 1 auto; display: flex; min-width: 0; }
.app-more > .app-tab { width: 100%; }
/* More opens over the page, above the bar, and scrolls inside itself. */
.app-more-panel { position: fixed; left: 0; right: 0; bottom: calc(var(--tabbar) + env(safe-area-inset-bottom)); z-index: 30; display: grid; gap: var(--space-3); max-height: calc(100vh - var(--tabbar) - 60px); overflow-y: auto; padding: var(--space-4); background: var(--surface); border-top: 1px solid var(--border); box-shadow: 0 -12px 30px rgba(17, 24, 39, 0.12); }
.app-more-foot { display: grid; gap: var(--space-2); justify-items: start; padding-top: var(--space-3); border-top: 1px solid var(--border); }
@media (max-width: 1023px) {
  body.app-page { padding-bottom: calc(var(--tabbar) + env(safe-area-inset-bottom)); }
  .app-tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; display: flex; align-items: stretch; min-height: var(--tabbar); padding: 4px 6px 0; padding-bottom: env(safe-area-inset-bottom); background: var(--surface); border-top: 1px solid var(--border); }
}

@media (min-width: 1024px) {
  .app-body { display: grid; grid-template-columns: 256px minmax(0, 1fr); min-height: 100vh; }
  .app-side { position: sticky; top: 0; display: flex; flex-direction: column; gap: 2px; height: 100vh; overflow-y: auto; padding: 20px 14px; background: var(--navy); color: var(--on-navy); }
  .app-header { gap: var(--space-4); min-height: 72px; padding: 14px 32px; background: var(--surface); border-bottom: 1px solid var(--border); }
  .app-header-logo, .app-alerts { display: none; }
  .app-header .app-new { background: var(--primary); color: var(--white); }
  .app-header .app-new:hover { background: var(--primary-hover); }
  .app-header .app-new .icon { display: block; }
  .app-lang { display: flex; margin-left: auto; }
}
/* The sidebar on navy. */
.app-side .logo { padding: 4px 10px 18px; }
.app-side .logo img { height: 26px; }
.app-side .account { margin-bottom: 12px; padding: 10px 12px; border: 1px solid var(--navy-line); border-radius: var(--radius-md); background: rgba(255, 255, 255, 0.05); }
.app-side .account-initials { width: 28px; height: 28px; background: var(--link); font-size: 12px; }
.app-side .account .account-name { color: var(--white); }
.app-side .account-plan { color: var(--on-navy-muted); }
.app-side .account-over .account-plan { color: var(--line-warning); }
.app-side .app-links a { color: var(--on-navy); }
.app-side .app-links a:hover { background: rgba(255, 255, 255, 0.08); color: var(--white); }
.app-side .app-links a.on { background: rgba(37, 99, 235, 0.45); color: var(--white); font-weight: 600; }
.app-side .app-group { color: var(--on-navy-muted); }
.app-side-foot { display: flex; align-items: center; gap: 10px; margin-top: auto; padding-top: 14px; border-top: 1px solid var(--navy-line); font-size: 13px; line-height: 18px; }
.user-initials { flex: none; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; background: var(--avatar-on-navy); color: var(--white); font: 700 12px/16px var(--font-sans); }
.user-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--name-on-navy); }
.app-side-foot form { margin: 0; }
.app-side-foot .btn-link { min-height: 44px; color: var(--on-navy-accent); font-size: 13px; }

/* ---------- The Visits page and search (D-260, D-261) ---------- */
/* The filters: as many to a row as fit, one under the other on a phone. */
.filters { max-width: none; }
/* The filters fold away in a <details> until one is set (D-264). */
.view .filters { display: block; }
.filters > summary { list-style: none; position: relative; padding: var(--space-2) var(--space-8) var(--space-2) var(--space-2); margin: calc(-1 * var(--space-2)); border-radius: var(--radius-md); font: 600 15px/22px var(--font-sans); color: var(--ink); cursor: pointer; }
.filter-form { display: grid; gap: var(--space-4); margin-top: var(--space-4); }
.filter-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); gap: var(--space-3) var(--space-4); align-items: start; }
.pager { justify-content: space-between; }
/* The search box (D-261): in the top bar from 1,024 px, and under the phone's More. The
   magnifier sits inside the field; the button stays, as no script submits the form. */
.app-search { display: none; align-items: center; gap: var(--space-2); margin: 0; }
.app-search label { position: relative; flex: 1 1 auto; min-width: 0; }
.app-search label .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.app-search .input { min-height: 44px; padding: var(--space-2) var(--space-3) var(--space-2) 40px; border-color: var(--line-input); background: var(--surface-sunk); font-size: 15px; line-height: 22px; box-shadow: none; }
.app-search-more { display: flex; }
@media (min-width: 1024px) {
  .app-search-header { display: flex; flex: 1 1 320px; max-width: 520px; }
}

/* On a phone each visit is a block: the time and the outcome on the first line, then the point,
   the person, the reason, the checks and the note. It is the same table; only its drawing
   changes, and its roles keep it a table for a screen reader (D-264). */
@media (max-width: 639px) {
  .table-stack { display: block; }
  .table-stack tbody { display: block; }
  .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-stack tr { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); padding: var(--space-3); border-bottom: 1px solid var(--border); }
  .table-stack td { display: block; grid-column: 2 / -1; min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: anywhere; }
  .table.table-stack td.text { min-width: 0; }
  .table-stack td:empty { display: none; }
  .table-stack .when { grid-column: 1; grid-row: 1 / span 6; font-weight: 600; }
  .table-stack .cell-outcome { grid-column: 3; grid-row: 1; justify-self: end; }
  .table-stack .who, .table-stack .cell-who { grid-column: 2; }
  .table-stack td[data-label]::before { content: attr(data-label); display: block; font-size: 12px; line-height: 16px; color: var(--muted); }
  .table-stack .cell-who { color: var(--ink); }
  .table-stack .cell-reason { color: var(--body); }
  .table-stack .cell-checks { padding-top: var(--space-1); }
  .table-stack .cell-note { color: var(--body); }
}

/* The same blocks wherever the history's own card is narrow: on the point page it sits beside the
   side column, so a wide screen can still give it a narrow card (D-287). Wider cards keep the table. */
@container history (max-width: 899px) {
  .table-stack { display: block; }
  .table-stack tbody { display: block; }
  .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-stack tr { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); padding: var(--space-3); border-bottom: 1px solid var(--border); }
  .table-stack td { display: block; grid-column: 2 / -1; min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: anywhere; }
  .table.table-stack td.text { min-width: 0; }
  .table-stack td:empty { display: none; }
  .table-stack .when { grid-column: 1; grid-row: 1 / span 6; font-weight: 600; }
  .table-stack .cell-outcome { grid-column: 3; grid-row: 1; justify-self: end; }
  .table-stack .who, .table-stack .cell-who { grid-column: 2; }
  .table-stack td[data-label]::before { content: attr(data-label); display: block; font-size: 12px; line-height: 16px; color: var(--muted); }
  .table-stack .cell-who { color: var(--ink); }
  .table-stack .cell-reason { color: var(--body); }
  .table-stack .cell-checks { padding-top: var(--space-1); }
  .table-stack .cell-note { color: var(--body); }
}

/* ---------- The point form (D-268 to D-273) ---------- */
/* One column on a phone: the form, then "This point at a glance". From 1024 px, side by side. */
.point-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.point-form-main { display: grid; gap: var(--space-4); min-width: 0; }
.point-top { display: grid; gap: var(--space-4); }
.view .form-section, .view .more-options { display: block; padding: 0; }
.form-section > summary, .more-options > summary { list-style: none; position: relative; display: grid; gap: var(--space-1); padding: var(--space-4) calc(var(--space-6) + 24px) var(--space-4) var(--space-6); border-radius: var(--radius-lg); cursor: pointer; }
/* Every fold shows that it opens: a chevron that turns when it is open, and a hover state.
   The browser's own triangle is hidden so there is one cue. No script (D-279). */
.form-section > summary::-webkit-details-marker, .more-options > summary::-webkit-details-marker, .filters > summary::-webkit-details-marker, .more-filters > summary::-webkit-details-marker { display: none; }
.form-section > summary::after, .more-options > summary::after, .filters > summary::after, .more-filters > summary::after { content: ""; position: absolute; top: 50%; right: var(--space-6); width: 9px; height: 9px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: translateY(-75%) rotate(45deg); transition: transform 150ms ease; }
.filters > summary::after { right: var(--space-3); }
.form-section[open] > summary::after, .more-options[open] > summary::after, .filters[open] > summary::after, .more-filters[open] > summary::after { transform: translateY(-25%) rotate(225deg); }
.form-section > summary:hover, .more-options > summary:hover, .filters > summary:hover, .more-filters > summary:hover { background: var(--surface-sunk); }
.form-section > summary:hover::after, .more-options > summary:hover::after, .filters > summary:hover::after, .more-filters > summary:hover::after { border-color: var(--ink); }
@media (prefers-reduced-motion: reduce) { .form-section > summary::after, .more-options > summary::after, .filters > summary::after, .more-filters > summary::after { transition: none; } }
.section-title { font: 700 17px/24px var(--font-sans); color: var(--ink); }
.section-summary { font-size: 14px; line-height: 20px; color: var(--body); }
.section-body { display: grid; gap: var(--space-4); padding: 0 var(--space-6) var(--space-6); }
.choices-row { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); }
.input-short { max-width: 160px; }
/* Days as buttons: real checkboxes, one tap each, wrapping on a phone. */
.day-choices { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.day-choice { position: relative; display: inline-flex; align-items: center; justify-content: center; min-width: 52px; min-height: 44px; padding: 0 var(--space-3); border: 1px solid var(--border-strong); border-radius: var(--radius-md); font-weight: 600; color: var(--ink); cursor: pointer; }
.day-choice input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.day-choice:has(input:checked) { border: 2px solid var(--primary); background: var(--tint); color: var(--primary); }
.day-choice:has(input:focus-visible) { outline: 2px solid var(--link); outline-offset: 2px; }
.form-footer { display: grid; gap: var(--space-4); }
.form-footer .actions { justify-content: flex-end; }
.glance { gap: var(--space-3); }
.glance-lines { display: grid; gap: var(--space-1) var(--space-3); margin: 0; }
.glance-lines dt { font: 600 13px/18px var(--font-sans); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.glance-lines dd { margin: 0 0 var(--space-2); color: var(--ink); }
/* A field under a choice is shown, and hidden only once the opposite choice is checked, so a
   browser without :has() shows everything and the form still works (D-271). */
.reveal { display: grid; gap: var(--space-4); }
.form-section:has(input[name="photo_mode"][value="off"]:checked) .reveal-photo-required,
.form-section:has(input[name="photo_mode"][value="optional"]:checked) .reveal-photo-required { display: none; }
.form-section:has(input[name="access_mode"][value="anyone"]:checked) .reveal-approved { display: none; }
.point-form:has(input[name="location_mode"][value="off"]:checked) .reveal-location { display: none; }
.form-section:has(input[name="hours_set"][value="any"]:checked) .reveal-hours { display: none; }
.form-section:has(input[name="scan_out"]:not(:checked)) .reveal-minutes { display: none; }
.form-footer:has(input[name="save_template"]:not(:checked)) .reveal-template { display: none; }
@media (min-width: 1024px) {
  .point-form { grid-template-columns: minmax(0, 1fr) 300px; }
  .glance { position: sticky; top: var(--space-4); }
}

/* ---------- The dashboard (D-256) ---------- */
.dash-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: var(--space-4); }
/* Four counters: four across with room, two by two or one under the other on a phone. */
.kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
/* Label, figure and small line are three rows every counter of a row shares, so a label that wraps
   moves the whole row's figures together and they stay on one line (D-297). */
.view .kpi { grid-row: span 3; grid-template-rows: subgrid; row-gap: var(--space-1); padding: 12px; color: var(--body); text-decoration: none; }
.kpi:hover { border-color: var(--line-input); box-shadow: var(--shadow-sm); }
/* A label wraps at its spaces, never inside a word, so two counters fit a phone's row (D-259). */
.kpi-label { display: flex; align-items: flex-start; gap: var(--space-2); font: 600 14px/20px var(--font-sans); color: var(--body); overflow-wrap: normal; }
/* The counter's icon in the colours of the status it counts (D-354). */
.kpi-icon { flex: none; display: none; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: var(--radius-md); }
.kpi-good .kpi-icon { background: var(--tint); color: var(--primary); }
.kpi-warning .kpi-icon { background: var(--warning-bg); color: var(--warning); }
.kpi-problem .kpi-icon { background: var(--danger-bg); color: var(--danger); }
.kpi-value { align-self: last baseline; font: 800 32px/38px var(--font-display); color: var(--ink); font-variant-numeric: tabular-nums; }
.kpi-note { min-height: 20px; font-size: 13px; line-height: 20px; color: var(--muted); }
/* A date as a figure: a heading's size, on one line, so it fits a phone's card (D-289). */
.kpi-value.kpi-date { font: 800 20px/28px var(--font-display); white-space: nowrap; }
/* A card's heading with what goes beside it: a legend, a count, a link. */
.card-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-2) var(--space-4); }
.card-head h2 { margin: 0; }
.card-head .chip { margin-left: 0; }
.page-title { display: grid; gap: var(--space-1); min-width: 0; }
.dash-last { margin: 0; font-size: 14px; line-height: 20px; color: var(--muted); }
.dash-head .btn .icon, .point-head .btn .icon { flex: none; }
.dash-columns { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-6); }
.dash-chart { flex: 2 1 420px; min-width: 0; }
.dash-attention { flex: 1 1 300px; min-width: 0; }
/* Fourteen days as bars, in plain boxes: completed below, not completed above it. */
.chart { display: flex; align-items: flex-end; gap: var(--space-1); height: 200px; border-bottom: 1px solid var(--border); }
.chart-day { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.bar { display: block; }
/* The two differ in lightness, not in hue alone: a dark bar, and a light one with an edge. */
.bar-done { background: var(--primary); border-radius: 0 0 2px 2px; }
.bar-not { box-sizing: border-box; background: var(--danger-bg); border: 1px solid var(--danger); border-radius: 4px 4px 0 0; }
.chart-today .bar-done { background: var(--link); }
/* An empty bar draws nothing, not a line of its border. */
.bar[style="height: 0.0%"], .bar[style="height: 0%"] { border: 0; }
/* The day of the month under each bar, Today under the last: one cell a bar, as the bars are laid. */
.chart-axis { display: flex; gap: var(--space-1); font-size: 12px; line-height: 16px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chart-axis span { flex: 1 1 0; min-width: 0; text-align: center; overflow: hidden; text-overflow: clip; white-space: nowrap; }
.chart-axis span:last-child { color: var(--ink); font-weight: 600; overflow: visible; }
.legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); font-size: 13px; line-height: 20px; }
.legend-mark { display: inline-block; width: 12px; height: 12px; margin-right: var(--space-1); vertical-align: -1px; border-radius: 2px; }
/* For a screen reader only: in the page, out of sight, taking no room. The standard rule, on a
   plain box: a table given this class keeps its own width and widens the page (D-259). Never
   display: none, which hides it from a screen reader too. */
/* The copyright line, small and muted, on its own line at the foot of the shared footer (D-348). */
.footer-copy { margin: var(--space-3) 0 0; font-size: 12px; line-height: 16px; color: var(--muted); }
@media (max-width: 639px) { .footer-copy { text-align: center; } }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; }
/* On a phone the badge sits above the point and its details; beside them from 640 px (D-259). */
.attention-item { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; gap: var(--space-2) var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); }
.attention-item .badge { justify-self: start; }
.attention-text { display: grid; gap: 2px; min-width: 0; }
.attention-text a { font-weight: 600; color: var(--ink); }
.dash-latest { display: grid; gap: var(--space-4); min-width: 0; }
/* Two counters to a row on a phone, four with room; one to a row only below any phone we aim at. */
@media (max-width: 299px) {
  .kpis { grid-template-columns: minmax(0, 1fr); }
}
@media (min-width: 640px) {
  h1 { font-size: 32px; line-height: 40px; }
  .point-tile { display: flex; }
  .kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }
  .view .kpi { padding: 20px; }
  .kpi-icon { display: flex; }
  .kpi-label { align-items: center; }
  .kpi-value { font-size: 36px; line-height: 40px; }
  .attention-item { grid-template-columns: auto minmax(0, 1fr); }
  .attention-item .badge { margin-top: 2px; }
  .attention-item .actions { grid-column: 2; }
}

/* On paper a page is plain blocks, so each sheet of labels can start a new page. */
@media print {
  .view { display: block; }
  .app-body { display: block; }
}

/* --- The point page (D-282) ---------------------------------------------------------------- */
.point-page { gap: var(--space-6); }
.point-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: var(--space-4); }
.point-title { display: grid; gap: var(--space-2); min-width: 0; }
.title-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.title-row h1 { margin: 0; overflow-wrap: anywhere; }
/* Links, one a tab. A language whose four words are wider than the screen scrolls this row
   sideways inside itself, by touch or by moving the focus; the page never scrolls sideways. The
   bar is hidden: a fade at the right edge says there is more that way (D-288). */
.point-tabs { display: flex; gap: var(--space-1); min-width: 0; max-width: 100%; overflow-x: auto; border-bottom: 1px solid var(--border); scrollbar-width: none; }
.point-tabs::-webkit-scrollbar { display: none; }
/* Sticks to the right edge while the row has more to show; once the row fits, or is scrolled to its
   end, it sits in its own room after the last tab and covers nothing. */
.point-tabs::after { content: ""; flex: none; width: 20px; position: sticky; right: 0; margin-left: auto; pointer-events: none; background: linear-gradient(to right, transparent, var(--page)); }
.point-tabs a { flex: none; white-space: nowrap; padding: 10px var(--space-4); min-height: 44px; box-sizing: border-box; border-bottom: 2px solid transparent; color: var(--body); font: 600 15px/22px var(--font-sans); text-decoration: none; }
.point-tabs a:hover { color: var(--ink); background: var(--surface-sunk); }
.point-tabs a[aria-current="page"] { border-bottom-color: var(--primary); color: var(--primary); }
/* On a phone the tabs lose their gap and take 8 px a side, so English and Spanish fit 360 px (D-288);
   from 640 px they keep the room the kit gives them (D-297). */
@media (max-width: 639px) {
  .point-tabs { gap: 0; }
  .point-tabs a { padding: 10px var(--space-2); }
}
.point-panel { display: grid; gap: var(--space-6); min-width: 0; }
/* The part live.js swaps in (D-337): no box of its own, so the page's grid and gaps are as before. */
.live-region { display: contents; }
/* The main column and the side column; the side goes under the main one below 1,024 px. */
.point-columns { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.point-main, .point-side { display: grid; gap: var(--space-6); min-width: 0; }
.follow-up-card { display: grid; gap: var(--space-3); border-color: var(--danger); }
.follow-up-text { display: grid; gap: var(--space-2); justify-items: start; }
.follow-up-text p { margin: 0; color: var(--ink); }
.view .history { gap: var(--space-4); container: history / inline-size; }
.code-text { overflow-wrap: anywhere; }
.history-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-3); }
.history-head h2 { margin: 0; }
.filter-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.filter-chip { display: inline-flex; align-items: center; min-height: 36px; padding: 0 var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-pill); color: var(--body); font: 600 14px/20px var(--font-sans); text-decoration: none; }
.filter-chip:hover { border-color: var(--border-strong); color: var(--ink); }
.filter-chip[aria-current="page"] { border-color: var(--primary); background: var(--tint); color: var(--primary); }
.code-card .qr-preview { justify-self: center; }
.side-people { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.side-people li { display: flex; justify-content: space-between; gap: var(--space-2); color: var(--ink); overflow-wrap: anywhere; }
@media (min-width: 1024px) {
  .point-columns { grid-template-columns: minmax(0, 1fr) 320px; }
}

/* ---------- Redesign round B: the pieces the four pages share (D-354 to D-356) ---------- */
/* The top bar's languages, EN · FR · ES. */
.app-lang { align-items: center; gap: 2px; font-size: 13px; line-height: 18px; }
.app-lang a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 6px; color: var(--muted); text-decoration: none; }
.app-lang a + a::before { content: "·"; margin-right: 10px; color: var(--muted); }
.app-lang a[aria-current="true"] { color: var(--ink); font-weight: 700; }
/* A segmented control made of links: a grey track, the current one white. Each is a 44 px target. */
.seg { display: inline-flex; flex-wrap: wrap; gap: 4px; max-width: 100%; padding: 4px; border-radius: var(--radius-md); background: var(--page); }
.view .seg { justify-self: start; }
.seg a { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 4px 14px; border-radius: 8px; color: var(--body); font: 600 14px/20px var(--font-sans); text-decoration: none; white-space: nowrap; }
.seg a:hover { color: var(--ink); }
.seg a[aria-current="page"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12); }
.seg-count { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
@media (pointer: coarse) { .seg a { min-height: 44px; } }
/* A time over its date, in a table's first column. */
.when-time { display: block; color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.when-date { display: block; font-size: 12px; line-height: 16px; color: var(--muted); font-weight: 400; }
/* The point's zone under the time, short, its full name on hover (D-383). */
.when-zone { display: block; font-size: 12px; line-height: 16px; color: var(--muted); font-weight: 400; }
.zone[title] { cursor: help; }
/* The time-zone picker's search box sits right above its list (D-383). */
.zone-picker .zone-search { margin-bottom: var(--space-2); }
.meta + .meta, .who-name + .meta, .point-cell-text .meta { display: block; }
.cell-who .meta, .cell-last .meta { display: block; }
/* A pill: the status beside a page's title. */
.badge-pill { border-radius: var(--radius-pill); padding: 2px 10px; }
/* Two letters for a name, drawn for the eye. */
.tile { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: var(--radius-md); background: var(--navy); color: var(--on-navy-accent); font: 700 12px/16px var(--font-sans); }
.avatar { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: var(--tint); color: var(--primary); font: 700 12px/16px var(--font-sans); }
/* The rules as short grey chips. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.chips li { padding: 2px 8px; border-radius: var(--radius-sm); background: var(--page); color: var(--chip-ink); font: 600 12px/16px var(--font-sans); }

/* The Points list (D-355). */
.point-cell { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.point-cell-text { display: grid; gap: 2px; justify-items: start; min-width: 0; }
.point-cell-text a { color: var(--ink); font-weight: 700; text-decoration: none; }
.point-cell-text a:hover { color: var(--primary); text-decoration: underline; }
.table-points td { vertical-align: middle; }
.table-points .cell-rules { min-width: 260px; }
.cell-select .check { justify-content: center; }
.cell-select input { width: 18px; height: 18px; accent-color: var(--primary); }
/* Below 640 px a point is a card: the box and the point on the first line, then the rules and
   the last visit. Its roles keep it a table for a screen reader. */
@media (max-width: 639px) {
  .table-points { display: block; }
  .table-points tbody { display: block; }
  .table-points thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-points tr { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2) var(--space-3); padding: var(--space-4); border-bottom: 1px solid var(--border); }
  .table-points td { display: block; min-width: 0; padding: 0; border: 0; white-space: normal; overflow-wrap: anywhere; }
  .table-points .cell-select { grid-column: 1; grid-row: 1; align-self: center; }
  .table-points .cell-point { grid-column: 2; grid-row: 1; }
  .table-points .cell-rules, .table-points .cell-last { grid-column: 1 / -1; }
  .table.table-points .cell-rules { min-width: 0; }
  .table-points td[data-label]::before { content: attr(data-label); display: block; font-size: 12px; line-height: 16px; color: var(--muted); }
}

/* The point page (D-282, redrawn in D-356). */
.point-head { align-items: center; }
.point-tile { flex: none; display: none; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 14px; background: var(--navy); color: var(--on-navy-accent); }
.point-tile .icon { width: 28px; height: 28px; }
.point-head .point-title { flex: 1 1 320px; }
.point-head .lead { font-size: 15px; line-height: 22px; }
/* The tabs on a grey track, as the segmented control. */
.point-tabs { gap: 4px; padding: 4px; border-bottom: 0; border-radius: var(--radius-md); background: var(--track); justify-self: start; }
/* The fade at the right edge where the row can scroll (D-288), in the track's colour. */
.point-tabs::after { background: linear-gradient(to right, transparent, var(--track)); }
.point-tabs a { min-height: 40px; border-bottom: 0; border-radius: 8px; font-size: 14px; line-height: 22px; }
.point-tabs a:hover { background: rgba(255, 255, 255, 0.6); }
.point-tabs a[aria-current="page"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12); }
.filter-chips { gap: 4px; padding: 4px; border-radius: var(--radius-md); background: var(--page); }
.filter-chip { min-height: 36px; border: 0; border-radius: 8px; }
.filter-chip[aria-current="page"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12); }
/* A follow-up open today is a warning; an older one a problem, with its age in words. */
.follow-up-today { border-color: var(--line-warning); background: var(--warning-bg); }
.follow-up-older { border-color: var(--line-problem); background: var(--danger-bg); }
.follow-up-text { grid-auto-flow: row; }
/* The history's visits: the time over its date in a narrow first column. */
.view .history .when { width: 1%; }
/* The code card in navy, the code on a white tile, its address in the light blue. */
.view .code-card { background: var(--navy); border-color: var(--navy); color: var(--on-navy); }
.code-card h2 { color: var(--white); }
.code-card .meta { color: var(--on-navy); }
.code-card .code-text { color: var(--on-navy-accent); font-family: var(--font-mono); font-size: 12px; line-height: 18px; }
.qr-tile { justify-self: center; padding: 14px; border-radius: 14px; background: var(--white); }
.code-card .btn-secondary { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.2); color: var(--white); box-shadow: none; }
.code-card .btn-secondary:hover { background: rgba(255, 255, 255, 0.18); }
.code-card .actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* The rules' labels in small monospace capitals. */
.glance-lines dt { font: 600 11px/16px var(--font-mono); letter-spacing: 0.12em; }
.side-people li { align-items: center; justify-content: flex-start; gap: var(--space-3); }
.side-name { flex: 1 1 auto; min-width: 0; font-weight: 600; }

/* The Visits page's filter bar (D-356): the period, the point, the outcome and what was flagged in
   a row that wraps; the person and the dates under More filters. */
.view .filter-bar { display: grid; gap: var(--space-4); padding: 14px 16px; }
.filter-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); }
.filter-row .field { flex: 1 1 180px; min-width: 0; }
.filter-row .field:first-child { flex: 0 1 auto; }
.filter-bar .field-label { font-size: 12px; line-height: 16px; color: var(--muted); }
/* A fold like the others (D-279): its own chevron, which turns when it is open. */
.more-filters > summary { list-style: none; position: relative; display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-8) 0 var(--space-2); margin-left: calc(-1 * var(--space-2)); border-radius: var(--radius-md); color: var(--link); font: 600 14px/20px var(--font-sans); cursor: pointer; }
.more-filters > summary::after { right: var(--space-3); }
.more-filters[open] > summary { margin-bottom: var(--space-3); }
.more-filters .meta { margin-top: var(--space-2); }
.app-side-nav { display: block; }
.app-tab-label { max-width: 100%; overflow-wrap: break-word; }
.table-points .cell-point { min-width: 220px; }
.who-name { display: block; color: var(--ink); }

/* ---------- Redesign round C: real form controls in the new look (D-357) ---------- */
/* A segmented choice: today's radios, each inside its label, drawn on a grey track. The radio stays
   in the page, focusable and read out; only its circle is hidden. Each choice is a 44 px target. */
.seg-choice { display: inline-flex; flex-wrap: wrap; gap: 4px; max-width: 100%; justify-self: start; padding: 4px; border-radius: var(--radius-md); background: var(--page); }
.seg-choice .check { position: relative; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 6px 14px; border-radius: 8px; color: var(--body); font: 600 14px/20px var(--font-sans); cursor: pointer; }
.seg-choice .check:hover { color: var(--ink); }
.seg-choice .check:has(input:checked) { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12); }
/* Pills: today's checkboxes for reasons, each a round, 44 px target with a tick when chosen. */
.pill-choice { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.pill-choice .check { position: relative; display: inline-flex; align-items: center; min-height: 44px; padding: 8px 16px; border: 1px solid var(--line-input); border-radius: var(--radius-pill); background: var(--surface); color: var(--ink); font: 600 14px/20px var(--font-sans); cursor: pointer; }
.pill-choice .check:has(input:checked) { border: 2px solid var(--primary); padding: 7px 15px; background: var(--tint); color: var(--primary); }
.pill-choice .check:has(input:checked)::before { content: "✓"; margin-right: 6px; }
.seg-choice input, .pill-choice input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.seg-choice .check:has(input:focus-visible), .pill-choice .check:has(input:focus-visible) { outline: 2px solid var(--link); outline-offset: 2px; }
/* A switch: a real checkbox, drawn as a track and a knob. It posts "on" when on, as before. */
.switch { align-items: center; min-height: 44px; cursor: pointer; }
.switch input { flex: none; appearance: none; -webkit-appearance: none; position: relative; width: 44px; height: 26px; margin: 0; border-radius: var(--radius-pill); background: var(--line-input); cursor: pointer; transition: background 150ms ease; }
.switch input::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: var(--white); box-shadow: 0 1px 3px rgba(17, 24, 39, 0.25); transition: transform 150ms ease; }
.switch input:checked { background: var(--primary); }
.switch input:checked::after { transform: translateX(18px); }
.switch input:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .switch input, .switch input::after { transition: none; } }
/* A legend over a segmented choice reads like a field label. */
.view .group > legend { font: 600 15px/22px var(--font-sans); color: var(--ink); }
/* The breadcrumb over a page title. */
.crumbs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; font-size: 13px; line-height: 18px; color: var(--muted); }
.crumbs a { color: var(--muted); }
.crumbs a + span::before, .crumbs a + a::before { content: "/"; margin-right: 6px; color: var(--muted); }
.crumbs [aria-current="page"] { color: var(--ink); }
/* Rows inside a card: recipients, emails sent, closed follow-ups, recent reports. */
.list-card { display: grid; margin: 0; padding: 0; list-style: none; }
.list-card > li { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-2) var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--line-soft); overflow-wrap: anywhere; }
.list-card > li:first-child { border-top: 0; padding-top: 0; }
.list-main { display: grid; gap: 2px; flex: 1 1 200px; min-width: 0; }
.list-main strong { color: var(--ink); }
.list-side { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.list-side form { margin: 0; }
/* Labels in small monospace capitals beside their values. */
.label-list { display: grid; grid-template-columns: minmax(80px, auto) minmax(0, 1fr); gap: var(--space-2) var(--space-3); margin: 0; font-size: 14px; line-height: 20px; }
.label-list dt { font: 600 11px/20px var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.label-list dd { margin: 0; min-width: 0; overflow-wrap: anywhere; color: var(--ink); }
/* Two columns that wrap: a main column and a side one. */
.two-cols { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-6); }
.two-cols > .col-main { flex: 2 1 480px; min-width: 0; display: grid; gap: var(--space-4); }
.two-cols > .col-side { flex: 1 1 320px; min-width: 0; display: grid; gap: var(--space-4); }

/* The point form (D-268, redrawn in D-358): the folds stay, each a numbered card. The number is the
   stylesheet's, so the fold's markup and its one-line summary are as before. */
.point-form { counter-reset: section; }
.form-section > summary { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-3); align-items: center; }
.form-section > summary::before { counter-increment: section; content: counter(section); grid-row: 1 / span 2; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; background: var(--navy); color: var(--white); font: 700 13px/1 var(--font-sans); }
.form-section > summary .section-title { font-family: var(--font-display); font-size: 18px; }
.form-section > summary .section-summary { grid-column: 2; }
/* "This point at a glance" in navy, its four labels in small light-blue capitals. */
.view .glance { background: var(--navy); border-color: var(--navy); color: var(--on-navy); }
.glance h2 { color: var(--white); }
.glance .glance-lines dt { color: var(--on-navy-accent); }
.glance .glance-lines dd { color: var(--white); }
.glance .meta { color: var(--on-navy); }
.form-footer .switch { font-weight: 600; }

/* Follow-ups (D-359): two counters, then each open one as a card. */
.kpis-two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 640px) { .kpis.kpis-two { grid-template-columns: repeat(2, minmax(0, 260px)); } }
.view .follow-up { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-4); padding: 18px 20px; }
.follow-up-icon { flex: none; display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 12px; }
.follow-up-today .follow-up-icon { background: var(--warning-bg); color: var(--warning); }
.follow-up-older .follow-up-icon { background: var(--danger-bg); color: var(--danger); }
.follow-up-body { display: grid; gap: var(--space-1); flex: 1 1 280px; min-width: 0; }
.follow-up-title { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; }
.follow-up-title a { color: var(--ink); font-weight: 700; font-size: 16px; text-decoration: none; }
.follow-up-title a:hover { text-decoration: underline; }
.follow-up-quote { margin: 0; color: var(--ink); }
.follow-up-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); flex: 1 1 260px; justify-content: flex-end; }
.follow-up-actions .cell-form .input { min-width: 140px; }
@media (max-width: 639px) {
  .follow-up-actions { justify-content: stretch; }
  .follow-up-actions > .btn, .follow-up-actions .cell-form { flex: 1 1 100%; }
  .follow-up-actions .cell-form .btn { flex: 1 1 auto; }
}
.list-card .avatar .icon { width: 16px; height: 16px; }

/* Alerts (D-360): each setting a row with its choice under its name. */
.alert-form { display: grid; gap: var(--space-4); }
/* Spaced, not ruled: a fieldset would draw a top border through its legend. */
.view .setting-row { margin-top: var(--space-2); }

/* Reports (D-361): the point list only for Choose points, the dates only for Custom dates. Hidden
   only once the other choice is checked, so a browser without :has() shows both (as D-271). */
.report-form .reveal-points { margin-top: var(--space-2); }
.report-form .reveal-dates { display: flex; }
.report-form:has(input[name="scope"][value="account"]:checked) .reveal-points { display: none; }
.report-form:has(input[name="preset"]:not([value="custom"]):checked) .reveal-dates { display: none; }
.tint-box { margin: 0; padding: 14px 16px; border-radius: 12px; background: var(--tint); color: var(--primary-hover); font-size: 14px; line-height: 20px; }
.pdf-tile { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 40px; border-radius: 4px; background: var(--danger-bg); color: var(--danger); font: 800 10px/1 var(--font-sans); }

/* Organizations (D-362): a grid of cards, one column on a phone. */
.org-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: var(--space-4); }
.org-head { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.org-head .tile { width: 44px; height: 44px; border-radius: 12px; font-weight: 800; }
.org-head h2 { margin: 0; font-size: 17px; line-height: 24px; min-width: 0; overflow-wrap: anywhere; }
.org-head h2 a { color: var(--ink); text-decoration: none; }
.org-head h2 a:hover { text-decoration: underline; }
.org-card .join-code { font-size: 15px; }

/* Billing (D-363): the plan in a navy card; the active codes as a native meter. */
.view .plan-hero { display: flex; flex-wrap: wrap; gap: var(--space-6); padding: 26px 28px; background: var(--navy); border-color: var(--navy); color: var(--on-navy); }
.plan-hero-main { display: grid; gap: var(--space-2); flex: 2 1 320px; min-width: 0; }
.plan-hero-side { display: grid; gap: var(--space-2); align-content: start; flex: 1 1 260px; min-width: 0; }
.plan-hero .eyebrow { color: var(--on-navy-accent); }
.plan-hero .plan-hero-name { margin: 0; color: var(--white); font: 800 30px/36px var(--font-display); overflow-wrap: anywhere; }
.plan-hero-name span { color: var(--on-navy-muted); font: 600 16px/24px var(--font-sans); }
.plan-hero .lead { color: var(--on-navy); font-size: 15px; line-height: 22px; }
.plan-hero .meta { color: var(--on-navy); }
.plan-hero p { color: var(--on-navy); }
.plan-hero .btn-link { color: var(--on-navy-accent); }
.meter { display: block; width: 100%; height: 10px; border: 0; border-radius: var(--radius-pill); background: rgba(255, 255, 255, 0.15); }
.meter::-webkit-meter-bar { height: 10px; border: 0; border-radius: var(--radius-pill); background: rgba(255, 255, 255, 0.15); }
.meter::-webkit-meter-optimum-value, .meter::-webkit-meter-suboptimum-value, .meter::-webkit-meter-even-less-good-value { border-radius: var(--radius-pill); background: var(--on-navy-accent); }
.meter::-moz-meter-bar { border-radius: var(--radius-pill); background: var(--on-navy-accent); }
/* A light button on navy. */
.btn-light { background: var(--white); color: var(--primary-hover); font-weight: 700; }
.btn-light:hover { background: var(--tint); }
/* A plan card: the one in use outlined, with its flag. */
.plan { position: relative; }
.plan h3 { margin: 0; font-size: 17px; }
.plan-current, .plan-popular { border: 2px solid var(--primary); }
.plan > .badge-pill { justify-self: start; }

/* A template's form (D-365): each group of rules a card of its own; the selects are as before. */
.rules-form { max-width: 720px; }
.view .rules-form > .group { padding: var(--space-6); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-card); }
.view .rules-form > .group > legend { float: left; width: 100%; margin-bottom: var(--space-3); font: 700 18px/24px var(--font-display); }
.view .rules-form > .group > legend + * { clear: both; }
.view .rules-form > .card { display: grid; gap: var(--space-2); }

/* Search (D-365): a plain card form; each result a row. */
.view .search-form { display: grid; gap: var(--space-3); max-width: 720px; }
.result-list { display: grid; margin: 0; padding: 0; list-style: none; }
.result-list > li { padding: var(--space-3) 0; border-top: 1px solid var(--line-soft); overflow-wrap: anywhere; }
.result-list > li:first-child { border-top: 0; padding-top: 0; }
/* The print page (D-366): on a screen the sheets scroll inside their own box, so the page never
   scrolls sideways on a phone; on paper the box adds nothing. */
.print-preview { max-width: 100%; overflow-x: auto; }
@media print {
  .print-preview { overflow: visible; }
}

/* The public pages (D-364): sign-in, sign-up and the code in one roomy card; the legal pages with
   room between their sections; the plans as on Billing. */
body.public .view-narrow > .card { padding: 28px; }
body.public .view-narrow .card .form { gap: var(--space-4); }
.view .legal { gap: var(--space-3); }
.view .legal h2 { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--line-soft); font-size: 18px; line-height: 26px; }
.tags { display: flex; flex-wrap: wrap; gap: var(--space-1); }
/* A table's box holds what is positioned inside it, so a heading kept for screen readers scrolls
   with the table instead of widening the page on a phone (found on Privacy in round C). */
.table-wrap { position: relative; }
/* A receiver's answer on the delivery log (D-431): kept narrow, broken anywhere. */
.snippet { margin: 4px 0 0; max-width: 48ch; font-size: 12px; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---------- Settings: ways to sign in (D-374) ---------- */
.sign-in-ways { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; gap: var(--space-3); }
.sign-in-ways li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.sign-in-ways .inline-form { margin-left: auto; }

/* ---------- The use pages and About (D-384) ---------- */
.use-page { max-width: 760px; display: grid; gap: var(--space-6); }
.use-page section { display: grid; gap: var(--space-3); }
.use-page h2 { margin: 0; }
.breadcrumb { font-size: 14px; line-height: 20px; color: var(--muted); }
.breadcrumb a { color: var(--link); }
.use-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: 0; }
.use-steps { display: grid; gap: var(--space-2); margin: 0; padding-left: 24px; }
.use-step { padding-left: var(--space-1); }
.use-example { gap: var(--space-2); }
.use-settings { display: grid; gap: var(--space-2); margin: 0; }
.use-settings div { display: grid; grid-template-columns: minmax(140px, 1fr) 2fr; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line-soft); }
.use-settings dt { font-weight: 600; color: var(--ink); }
.use-settings dd { margin: 0; color: var(--body); }
.use-faq { display: grid; gap: var(--space-2); }
.use-faq details { padding: var(--space-3) var(--space-4); border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.use-faq summary { cursor: pointer; font-weight: 600; color: var(--ink); }
.use-faq p { margin: var(--space-2) 0 0; }
.use-cta { gap: var(--space-2); }
.use-others h2 { font-size: 18px; }
@media (max-width: 560px) {
  .use-settings div { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* ---------- Rounds (D-388) ---------- */
.round-stops { list-style: decimal; margin: 0; padding-left: 24px; display: grid; gap: var(--space-2); }
.round-stop { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line-soft); }
.round-stop[draggable="true"] { cursor: grab; }
.round-stop.dragging { opacity: 0.5; }
.round-stop-move { margin-left: auto; display: flex; gap: var(--space-1); }
.round-code { max-width: 220px; }
.round-code svg { width: 100%; height: auto; }

/* The long-form pages (D-416): the body is plain Markdown, so its elements are styled here. */
.content-body { display: grid; gap: var(--space-3); min-width: 0; }
.content-body h2 { margin: var(--space-3) 0 0; }
.content-body p, .content-body ul, .content-body ol { margin: 0; }
.content-body ul, .content-body ol { padding-left: 24px; display: grid; gap: var(--space-1); }
.content-body table { width: 100%; border-collapse: collapse; font-size: 14px; line-height: 20px; }
.content-body th, .content-body td { padding: 8px 10px; border: 1px solid var(--border); text-align: left; vertical-align: top; }
.content-body th { white-space: nowrap; overflow-wrap: normal; word-break: normal; }
.content-body td:empty { height: 32px; }
.content-body td:first-child { min-width: 96px; overflow-wrap: normal; word-break: normal; }
.content-body table { display: block; overflow-x: auto; }
.content-list { display: grid; gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
.content-list h2 { margin: 0 0 var(--space-1); font-size: 20px; line-height: 28px; }
.content-list p { margin: 0; color: var(--body); }
/* On a phone each fact stacks, with both answers on screen and named. */
@media (max-width: 639px) {
  #facts tr { grid-template-columns: minmax(0, 1fr); }
  #facts th[scope="row"] { display: block; padding: 0; border: 0; white-space: normal; }
  #facts td { grid-column: 1; }
  #facts td::before { content: attr(data-label); display: block; font-weight: 600; color: var(--ink); }
}

/* ---------- The public pages other than home: headings and the plan cards (D-242 onward) ---------- */
/* Their headings are Archivo, as on every page but the worker's (D-351, which ends Sora, D-245). */
body.public .plan .price { font-family: var(--font-display); font-weight: 700; }

/* Pricing: the plans' own cards, with the popular one outlined. */
.plan-popular { border: 2px solid var(--primary); }
/* The name's row is the same height in every card and never wraps, so the Popular tag adds no line. */
.plan-name { display: flex; flex-wrap: nowrap; justify-content: space-between; align-items: center; gap: var(--space-2); min-height: 24px; font-weight: 700; color: var(--ink); white-space: nowrap; }
.plan-name .badge { padding: 1px 6px; font-size: 11px; white-space: nowrap; }
/* A price's currency letters are set smaller, so the price stays on one line (D-249). */
.plan .price small { font-family: var(--font-sans); font-size: 12px; line-height: 16px; font-weight: 600; color: var(--muted); }
