/* Components (L2), the body — the largest part of the app's component CSS; the earlier part is components-early.css and the
 * app shell/page blocks follow in app-components.css (list order = cascade order, see Layout.kt STYLESHEETS).
 * 1. lab.css L2, verbatim — the sections whose class names the app does not emit yet (spec, sheet, field,
 *    choices, pills, type roles…). A DS-B lane that moves a component onto the lab look brings its lab section
 *    here and deletes the matching block from 2.
 * 2. COMPAT — DaisyUI 4.12.24's compiled component rules for exactly the classes the app still emits
 *    (rendered corpus + Kotlin/TS literals), colours rewritten onto tokens.css, radii onto --radius, the
 *    button-pop animation dropped. It keeps today's pixels while daisyui is gone from package.json. It only shrinks.
 * Plain rules, no `@layer`: nothing purges unused classes any more, so a rule with no emitter is dead weight — delete it. */
/* ── 1. lab L2 ── */
.num { font-variant-numeric: tabular-nums; }
.t-display { font-size: var(--t-display); font-weight: 700; line-height: var(--lh-tight); }
.t-title   { font-size: var(--t-title);   font-weight: 700; line-height: var(--lh-tight); color: var(--c-primary); }
.t-heading { font-size: var(--t-body);    font-weight: 700; line-height: var(--lh-tight); }
.t-body    { font-size: var(--t-body); }
.t-label   { font-size: var(--t-label);   color: var(--ink-3); line-height: var(--lh-body); }
.t-caption { font-size: var(--t-caption); color: var(--ink-3); line-height: var(--lh-body); }
.t-micro   { font-size: var(--t-micro);   font-weight: 600; color: var(--ink-3); }
/* M12 (int-specs/mobile/STANDARD.md, still binding): no ALL-CAPS on the phone — the micro role's caps are desktop-only. */
@media (min-width: 1024px) { .t-micro { letter-spacing: .06em; text-transform: uppercase; } }
/* Preflight gives <button> `text-transform: none`; a sort header (Lists.kt sortHeader) sits in a t-micro row and must caps with it. */
.t-micro :where(button) { text-transform: inherit; }
.stack   { display: flex; flex-direction: column; gap: var(--gap, var(--s4)); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap, var(--s2)); }
.between { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.grid-2  { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
.grid-3  { display: grid; gap: var(--s4); grid-template-columns: 1fr; }
.grow    { flex: 1 1 auto; min-width: 0; }
.pad     { padding: var(--s4); }
/* A child that takes the whole grid row (a form field, a section) — was Tailwind's `col-span-full`. */
.span-full { grid-column: 1 / -1; }
/* Tier visibility primitives: `phone-only` / `desk-only` hide a face per tier; `phone-sr-only` is Tailwind's `sr-only` below 1024
 * and shown from 1024 (the page h1, which the phone top bar already shows, M1). */
.phone-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }
@media (min-width: 1024px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .grid-3 { grid-template-columns: 1fr 1fr 1fr; }
  .pad { padding: var(--s5); }
  /* !important on purpose: a pure media gate nothing toggles, and it must beat every component's own display
     (.navbar, .actions, .btn …) — unlike .hidden, which JS reveals with style.display (render diff 2026-10-18). */
  .phone-only { display: none !important; }
  .phone-sr-only { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal; }
}
@media (max-width: 1023.98px) {
  .desk-only { display: none !important; }
}
.field { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.field > label { font-size: var(--t-label); color: var(--ink-3); }
.field > label b { font-weight: 600; color: var(--c-ink); }
.field .hint  { font-size: var(--t-caption); color: var(--ink-3); }
.field.is-error .hint  { color: var(--c-error); }
.check { display: flex; align-items: center; gap: var(--s3); min-height: var(--ctl); cursor: pointer; }
.check input { margin: 0; accent-color: var(--c-primary); }
.pills { display: flex; gap: var(--s2); overflow-x: auto; padding-bottom: var(--s1); scrollbar-width: none; }
.section { background: var(--c-bg); border: 1px solid var(--c-line); border-radius: var(--radius); padding: var(--s4); box-shadow: var(--shadow-rest); }
@media (min-width: 1024px) {
  .section { padding: var(--s5); }
}
.section-head { display: flex; align-items: baseline; gap: var(--s2); padding-bottom: var(--s2);
  margin-bottom: var(--s4); border-bottom: 1px solid var(--c-line); }
.section-head .num { font-size: var(--t-label); font-weight: 600; letter-spacing: .1em; color: color-mix(in srgb, var(--c-primary) 80%, transparent); }
.section-head h2  { font-size: var(--t-body); font-weight: 700; color: var(--c-primary); flex: 1; }
.section-head .count { font-size: var(--t-caption); color: var(--ink-3); }
.spec { display: grid; grid-template-columns: 1fr; gap: 0; margin: 0; border: 1px solid var(--c-line); border-radius: var(--radius); overflow: hidden; }
.spec > div { display: grid; grid-template-columns: 1fr; gap: var(--s1); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--c-line); }
.spec > div:nth-child(even) { background: var(--g-50); }
.spec > div:last-child { border-bottom: 0; }
.spec dt { font-size: var(--t-caption); color: var(--ink-3); margin: 0; }
.spec dd { margin: 0; font-size: var(--t-body); min-width: 0; overflow-wrap: anywhere; }
.spec dd.is-empty { color: var(--g-300); font-style: normal; }
.spec > div:has(dd.is-empty) dt { color: var(--g-500); }
.spec > div:has(dd.is-empty) { padding-top: var(--s1); padding-bottom: var(--s1); }
@media (min-width: 1024px) {
  /* Label and value share one 14px line box so their baselines meet. Each row is a subgrid of the dl, so the label
     column fits the group's longest label (capped at 50% of the dl, 30% per pair in is-2col) and every row aligns. */
  .spec { grid-template-columns: fit-content(50%) minmax(0, 1fr); }
  .spec > div { grid-template-columns: subgrid; grid-column: span 2; gap: 0; padding: 0; }
  .spec dt { font-size: var(--t-label); padding: var(--s3) var(--s4); border-right: 1px solid var(--c-line); background: var(--g-50); }
  .spec dd { font-size: var(--t-label); padding: var(--s3) var(--s4); }
  .spec > div:has(dd.is-empty) { padding: 0; }
  .spec > div:nth-child(even) { background: transparent; }
  .spec.is-2col { grid-template-columns: fit-content(30%) minmax(0, 1fr) fit-content(30%) minmax(0, 1fr); }
  .spec.is-2col > div:nth-child(4n+1), .spec.is-2col > div:nth-child(4n+2) { background: var(--g-50); }
  .spec.is-2col > div:nth-child(odd) { border-right: 1px solid var(--c-line); }
  /* an odd last row spans both pairs instead of leaving a blank half cell */
  .spec.is-2col > div:last-child:nth-child(odd) { grid-column: 1 / -1; border-right: 0; }
  .spec.is-2col > div:last-child:nth-child(odd) dd { grid-column: 2 / -1; }
}
.row { display: flex; gap: var(--s3); align-items: center; min-height: var(--row); padding: var(--s2) var(--s4);
  background: var(--c-bg); border-bottom: 1px solid var(--c-line); border-left: 4px solid var(--c-line);
  text-decoration: none; color: inherit; }
.row[data-edge="created"] { border-left-color: var(--c-accent); }
.row[data-edge="edited"]  { border-left-color: var(--c-warning); }
.row .title { font-weight: 600; font-size: var(--t-body); }
.row .sub   { font-size: var(--t-label); color: var(--ink-3); }
.row:hover { background: var(--g-50); }
.empty { padding: var(--s6) var(--s4); text-align: center; color: var(--ink-3); border: 1px dashed var(--c-line); }
.topbar { position: sticky; top: 0; z-index: var(--z-topbar); display: flex; align-items: center; gap: var(--s2);
  height: var(--h-topbar); padding: 0 var(--s2); background: var(--c-primary); color: #fff; }
.topbar .title { font-size: var(--t-body); font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bottom-nav { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-topbar); display: grid; grid-auto-flow: column;
  height: var(--h-bottomnav); background: var(--c-bg); border-top: 1px solid var(--c-line); }
.bottom-nav a { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-size: var(--t-micro); text-transform: none; letter-spacing: 0; color: var(--ink-3); text-decoration: none; }
.bottom-nav a[aria-current] { color: var(--c-primary); font-weight: 600; }
.bottom-nav svg { width: 24px; height: 24px; }
.sidebar { width: var(--w-sidebar); background: var(--c-primary); color: #fff; min-height: 100%; display: flex; flex-direction: column; }
.sidebar .brand { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); min-height: 56px; border-bottom: 1px solid rgb(255 255 255 / .15); }
.sidebar nav a { display: flex; align-items: center; gap: var(--s3); height: var(--ctl-m); padding: 0 var(--s4);
  color: rgb(255 255 255 / .8); text-decoration: none; font-size: var(--t-label); }
.sidebar nav a[aria-current] { background: rgb(255 255 255 / .12); color: #fff; font-weight: 600; box-shadow: inset 3px 0 0 var(--c-accent); }
.sidebar nav a:hover { background: rgb(255 255 255 / .08); }
.sidebar svg { width: 20px; height: 20px; }
.page-head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s4); }
.page-head h1 { font-size: var(--t-title); font-weight: 700; color: var(--c-primary); flex: 1; min-width: 0; }
dialog.sheet { border: 0; padding: 0; width: min(100vw, var(--w-sheet)); max-height: 85dvh; background: var(--c-bg); border-radius: var(--radius); box-shadow: var(--shadow-float); }
dialog.sheet::backdrop { background: var(--scrim); }
@media (max-width: 1023.98px) {
  dialog.sheet { margin: auto 0 0; width: 100vw; max-width: none; }
}
/* A wide card spends its width on columns: a stacked pick list flows two per row instead of scrolling one per row. */
@media (min-width: 1024px) {
  dialog.sheet.is-wide { width: min(100vw, var(--w-sheet-wide)); }
  /* Every grid form of .choices lines its chips up at the top (`align-items: start`): a one-line chip must not stretch to the
     tallest cell of its row (user 2026-10-27). */
  dialog.sheet.is-wide .choices.is-stack { display: grid; grid-template-columns: 1fr 1fr; align-items: start; }
  /* A long list of short labels on a row of its own (infiltração tipo de problema). */
  .choices.is-stack.is-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; }
}
.menu-panel { position: absolute; left: 0; top: calc(100% + 4px); z-index: var(--z-drawer); min-width: 100%; width: max-content; max-width: 360px; max-height: 320px; overflow: auto;
  scrollbar-width: thin; /* a panel that scrolls shows no ▲▼ buttons (Chromium draws them on the classic bar) */
  background: var(--c-bg); border: 1px solid var(--c-line); border-radius: var(--radius); box-shadow: var(--shadow-raise); padding: var(--s1); }
/* Menu ROWS only: a kit `.btn` inside a panel (date shortcuts, switcher Aplicar) keeps its own button look. */
.menu-panel label, .menu-panel a:not(.btn), .menu-panel button:not(.btn) { display: flex; align-items: center; gap: var(--s3); min-height: var(--ctl-m); padding: 0 var(--s3);
  border: 0; background: transparent; border-radius: var(--radius); font-size: var(--t-label); color: var(--c-ink); text-decoration: none; cursor: pointer; width: 100%; text-align: left; }
.menu-panel label:hover, .menu-panel a:not(.btn):hover, .menu-panel button:not(.btn):hover { background: var(--g-50); }
/* A row's tone class keeps its ink: the row rule above (0,2,1) outranks a utilities-layer `ink-error` (0,1,0), so a menu
   Excluir wore Editar's ink at both widths (ui-feedback 2026-10-13 F1 follow-up). (0,3,1) here. */
.menu-panel :is(a, button):not(.btn).ink-error { color: var(--c-error); }
.menu-panel :is(a, button):not(.btn).ink-success { color: var(--c-success); }
.menu-panel input { margin: 0; accent-color: var(--c-primary); }
.menu-panel label:has(input:checked) { background: color-mix(in srgb, var(--c-primary) 10%, var(--c-bg)); font-weight: 600; }
.menu-panel hr { border: 0; border-top: 1px solid var(--c-line); margin: var(--s1) 0; }
.menu-panel .head { font-size: var(--t-caption); padding: var(--s2) var(--s3) var(--s1); }
@media (max-width: 1023.98px) {
  /* bottom pad = the bottom chrome strip (nav + safe area; the safe area alone where the nav is hidden, app.css), so
     the last row never sits in the nav's band — the same token the sticky bar, toast and FAB read */
  .menu-panel { position: fixed; left: 0; right: 0; bottom: 0; top: auto; max-width: none; width: auto; max-height: 70dvh; border-radius: var(--radius) var(--radius) 0 0; box-shadow: var(--shadow-float); padding: var(--s2) var(--s2) calc(var(--s2) + var(--mobile-chrome-bottom-strip)); }
  .menu-panel label, .menu-panel a:not(.btn), .menu-panel button:not(.btn) { min-height: var(--ctl-l); }
}
.choices { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s2); }
/* A one-line chip is exactly --ctl tall (padding-block = half of what the label line leaves, less the border) and its mark sits on
   line 1; a label that wraps just grows the box, with body leading so the lines clear the border (user 2026-10-26) and the mark stays
   on the first line (2026-10-27). A card chip (`.choice-body`, components-early.css) keeps its own, higher-specificity padding. */
.choices label { display: inline-flex; align-items: flex-start; gap: var(--s2); min-height: var(--ctl); padding-inline: var(--s3);
  padding-block: calc((var(--ctl) - var(--t-label) * var(--lh-body)) / 2 - 1px);
  border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--c-bg); font-size: var(--t-label); line-height: var(--lh-body);
  text-wrap: pretty; cursor: pointer; }
.choices input { margin: 0; accent-color: var(--c-primary); }
/* the mark is centred on the label's first line whatever --check is (24 phone, 20 desktop): a negative margin where the box
   is taller than the line, so the one-line chip still measures --ctl */
.choices input:not(.sr-only) { margin-block: calc((var(--t-label) * var(--lh-body) - var(--check)) / 2); }
/* every kit checkbox/radio box reads one size token (tokens.css --check: 24 phone, 20 desktop); an empty required group's
   stand-in radio (Forms.kt choiceChips) is `sr-only`, which this selector would otherwise out-rank */
.check input, .menu-panel input, .choices input:not(.sr-only) { width: var(--check); height: var(--check); flex-shrink: 0; }
.choices label:has(input:checked) { border-color: var(--c-primary); background: color-mix(in srgb, var(--c-primary) 10%, var(--c-bg)); }
.choices.is-stack { flex-direction: column; }
.choices.is-stack label { width: 100%; }
/* a Sim/Não pair (Forms.kt choicesClasses): two equal chips side by side at every width, in a half cell on the desktop */
.choices.is-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
/* lab 01-kit (DS-D D1): the choice group's error ring, a chip the text filter hides, the filter's field */
.choices.is-error label { border-color: var(--c-error); }
.choices label[hidden] { display: none; }
/* a group over 12 options (Forms.kt longChoices): with a pick it shows only that chip + Alterar; open, the first 10 chips and the
   filter finds the rest (declarativeHandlers.ts drops is-capped while filtering and caps the matches itself). The blank "none" chip is no pick. */
.choice-long { display: flex; flex-direction: column; gap: var(--s2); align-items: flex-start; }
.choice-long > .search, .choice-long > .choices { align-self: stretch; }
.choice-long:has(.choices input:checked:not([value=""])):not(.is-open) > :is(.search, .choice-more),
.choice-long:has(.choices input:checked:not([value=""])):not(.is-open) .choices > label:not(:has(input:checked)),
.choice-long.is-capped .choices > label:nth-of-type(n+11):not(:has(input:checked)),
.choice-long:is(.is-open, :not(:has(.choices input:checked:not([value=""])))) > .choice-change { display: none; }
.choice-more { margin: 0; }
.search .input { padding-left: calc(var(--s3) + 24px); }
.search { position: relative; }
.search::before { content: ""; position: absolute; left: var(--s3); top: 50%; width: 18px; height: 18px; transform: translateY(-50%); pointer-events: none; opacity: .6;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230B111C' stroke-width='1.8'%3E%3Cpath d='m21 21-5.2-5.2M17 10.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0Z'/%3E%3C/svg%3E") center/contain no-repeat; }

/* Toast (utils/toast.ts, int-specs/review-2026-10-16/TOAST-SPEC.md). Toasts live in .toast-stack, newest on top. PHONE (<1024) is a
   two-line card: line 1 = tone icon + the message (all the remaining width) + the ✕ in the corner; line 2, only when there is one
   (.toast-extra), under the message text = the errorRef ("Ref: 22fff21a", quiet mono) on the left, the action on the right. DESKTOP
   keeps one row: .toast-extra dissolves and its children sit beside the message — except a ref, which stays its own line (.has-ref).
   Every button inside takes --ctl (set on the stack): 48 on a phone (M4), 32 on a desktop, 48 again under a coarse pointer; the ✕
   glyph stays small, only its target grows. */
.toast { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: start;
  gap: var(--s1) var(--s2); padding: var(--s2) var(--s2) var(--s2) var(--s3);
  background: var(--c-bg); color: var(--c-ink); border: 1px solid var(--c-line); border-left-width: 4px;
  border-radius: var(--radius); box-shadow: var(--shadow-float); font-size: var(--t-label); }
.toast[hidden] { display: none !important; }   /* folded behind .toast-fold; the desktop `display: flex` below would out-rank a plain rule */
.toast[data-tone="success"] { border-left-color: var(--c-success); }
.toast[data-tone="warning"] { background: var(--c-warning-soft); border-color: color-mix(in srgb, var(--c-warning) 40%, transparent); border-left-color: var(--c-warning); color: var(--c-warning); }
.toast[data-tone="error"]   { border-left-color: var(--c-error); }
.toast[data-tone="info"]    { border-left-color: var(--c-info); }
.toast > .toast-icon { grid-column: 1; grid-row: 1; margin-top: calc((var(--ctl) - 20px) / 2); }
.toast > .toast-msg { grid-column: 2; grid-row: 1; align-self: center; min-width: 0; overflow-wrap: anywhere; }
.toast > .toast-close { grid-column: 3; grid-row: 1; margin-left: calc(-1 * var(--s2)); }
.toast > .toast-extra { grid-column: 2 / -1; grid-row: 2; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s1) var(--s2); }
.toast-extra > .btn:last-child { margin-left: auto; }
/* the repeat counter ("2 vezes") rides the end of the message text */
.toast-count { display: inline-block; margin-left: var(--s1); padding: 0 var(--s2); border: 1px solid currentColor; border-radius: 9999px;
  font-size: var(--t-caption); font-weight: 600; white-space: nowrap; }
.toast .btn { border-color: currentColor; color: inherit; background: transparent; }
/* The close × is the one toast button with no label: the outline belongs to the action beside it ("Desfazer"), and a
   ring around a bare ✕ read as a second tone icon, larger than the message (user 2026-10-14). `btn-ghost:hover` drops
   the border anyway, so a ringed ✕ also lost it under the cursor — this keeps the two states one look. */
.toast .btn-circle { border-color: transparent; }
/* ── 12 · undo: the 8 s time bar under a toast whose action takes the write back (toast.ts, windowMs) ── */
.toast:has(> .toast-bar) { overflow: hidden; }
.toast-bar { position: absolute; left: 0; bottom: 0; width: 100%; height: 3px; background: currentColor; transform-origin: left;
  animation: toast-bar-shrink linear forwards; }
.toast:hover > .toast-bar, .toast:focus-within > .toast-bar { animation-play-state: paused; }
@keyframes toast-bar-shrink { to { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .toast-bar { display: none; } }
/* Container (frontend/ts/utils/toast.ts): the fixed column; each .toast inside flows, so several stack top-down 8px apart.
   z 1100 stays above dialogs and the annotator overlay (z 1000). Past the cap (2 phone / 3 desktop) the older toasts are
   `hidden` and one .toast-fold row closes the stack; tapped, the stack becomes a 60vh scroll list and the row reads "Recolher". */
.toast-stack { --ctl: var(--ctl-l); position: fixed; left: var(--s4); right: var(--s4); top: calc(var(--h-topbar) + var(--s3)); z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--s2); pointer-events: none; }
.toast-stack > * { flex-shrink: 0; pointer-events: auto; }
.toast-stack .btn { height: var(--ctl); min-height: var(--ctl); }
.toast-stack .btn-circle { width: var(--ctl); }
.toast-stack .toast-fold { width: 100%; background: var(--c-bg); color: var(--c-ink); border: 1px solid var(--c-line); box-shadow: var(--shadow-float); font-size: var(--t-label); }
.toast-stack[data-expanded="true"] { max-height: 60vh; overflow-y: auto; overscroll-behavior: contain; pointer-events: auto; }
.toast-stack > .toast-fold { position: sticky; bottom: 0; }
@media (min-width: 1024px) {
  .toast-stack { --ctl: var(--ctl-s); left: 50%; right: auto; transform: translateX(-50%); top: var(--s4); width: 560px; max-width: calc(100vw - 2 * var(--s4)); }
  /* one row, unless an errorRef is on it: the ref is a line under the message (user 2026-10-26), so that toast keeps the phone's two lines */
  .toast:not(.has-ref) { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); }
  .toast:not(.has-ref) > .toast-icon { margin-top: 0; flex-shrink: 0; }
  .toast:not(.has-ref) > .toast-msg { flex: 1 1 0%; }
  .toast:not(.has-ref) > .toast-extra { display: contents; }
  .toast:not(.has-ref) .btn { flex-shrink: 0; }
  .toast:not(.has-ref) > .toast-close { margin-left: 0; }
  .toast:not(.has-ref) .toast-extra > .btn:last-child { margin-left: 0; }
}
/* Touch at desktop width: the finger, not the layout, sets the target (tokens.css) */
@media (min-width: 1024px) and (pointer: coarse) { .toast-stack { --ctl: var(--ctl-l); } }

/* ── 2. COMPAT (DaisyUI 4.12.24, generated by DS-B WP-0) ── */
:root, [data-theme] { background-color: var(--g-0); color: var(--g-900); }
:root { --animation-btn: 0.25s; --animation-input: .2s; --btn-focus-scale: 0.95; --border-btn: 1px; --tab-border: 1px; }
html { -webkit-tap-highlight-color: transparent; }
.alert {
  display: grid;
  width: 100%;
  grid-auto-flow: row;
  align-content: flex-start;
  align-items: center;
  justify-items: center;
  gap: 1rem;
  text-align: center;
  border-radius: var(--radius);
  border-width: 1px;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  padding: 1rem;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  --alert-bg: var(--g-100);
  --alert-bg-mix: var(--g-0);
  background-color: var(--alert-bg)
}
@media (min-width: 640px) {
  .alert {
      grid-auto-flow: column;
      grid-template-columns: auto minmax(auto,1fr);
      justify-items: start;
      text-align: start
    }
}
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  transition-duration: 200ms;
  height: 1.25rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  width: -moz-fit-content;
  width: fit-content;
  padding-left: 0.563rem;
  padding-right: 0.563rem;
  border-radius: var(--radius);
  border-width: 1px;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
@media (hover:hover) {
  .checkbox-primary:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent)
    }
  .checkbox-warning:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-border-opacity) * 100%), transparent)
    }
  .checkbox-error:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
    }
  .label a:hover {
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  .menu li > *:not(ul, .menu-title, details, .btn):active,
  .menu li > *:not(ul, .menu-title, details, .btn).active,
  .menu li > details > summary:active {
      --tw-bg-opacity: 1;
      background-color: color-mix(in srgb, var(--c-neutral) calc(var(--tw-bg-opacity) * 100%), transparent);
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--c-neutral-ink) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  .radio-primary:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent)
    }
  .radio-secondary:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--c-secondary) calc(var(--tw-border-opacity) * 100%), transparent)
    }
  .tab:hover {
      --tw-text-opacity: 1
    }
}
.btn {
  display: inline-flex;
  height: 3rem;
  min-height: 3rem;
  flex-shrink: 0;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  border-color: transparent;
  border-color: color-mix(in srgb, var(--btn-color, var(--g-100)) calc(var(--tw-border-opacity) * 100%), transparent);
  padding-left: 1rem;
  padding-right: 1rem;
  text-align: center;
  font-size: 0.875rem;
  line-height: 1em;
  gap: 0.5rem;
  font-weight: 600;
  text-decoration-line: none;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  border-width: var(--border-btn, 1px);
  transition-property: color, background-color, border-color, opacity, box-shadow, transform;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
  outline-color: var(--g-900);
  background-color: color-mix(in srgb, var(--btn-color, var(--g-100)) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  --tw-border-opacity: 1
}
.btn-disabled,
.btn[disabled],
.btn:disabled {
  pointer-events: none
}
/* A tinted glyph dims with its button's word: a live-green + on a dead Entrada read as clickable (replica walk 2026-10-23). */
:is(.btn-disabled, .btn:disabled, .btn[aria-disabled="true"]) > :is(.ink-success, .ink-error) { color: inherit; }
.btn-square {
  height: 3rem;
  width: 3rem;
  padding: 0px
}
.btn-circle {
  height: 3rem;
  width: 3rem;
  border-radius: 9999px;
  padding: 0px
}
:where(.btn:is(input[type="checkbox"])),
:where(.btn:is(input[type="radio"])) {
  width: auto;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none
}
.btn:is(input[type="checkbox"]):after,
.btn:is(input[type="radio"]):after {
  --tw-content: attr(aria-label);
  content: var(--tw-content)
}
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius)
}
.card:focus {
  outline: 2px solid transparent;
  outline-offset: 2px
}
.card-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  padding: var(--padding-card, 2rem);
  gap: 0.5rem
}
.card-body :where(p) {
  flex-grow: 1
}
.card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.5rem
}
.card figure {
  display: flex;
  align-items: center;
  justify-content: center
}
.checkbox {
  flex-shrink: 0;
  --chkbg: var(--g-900);
  --chkfg: var(--g-0);
  height: 1.5rem;
  width: 1.5rem;
  cursor: pointer;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.2
}
.collapse:not(td):not(tr):not(colgroup) {
  visibility: visible
}
.collapse {
  position: relative;
  display: grid;
  overflow: hidden;
  /* minmax(0,1fr): a wide table inside scrolls in its own wrapper instead of widening the grid past the clip (walk 2026-10-13) */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: max-content 0fr;
  transition: grid-template-rows 0.2s;
  width: 100%;
  border-radius: var(--radius)
}
.collapse-title,
.collapse > input[type="checkbox"],
.collapse > input[type="radio"],
.collapse-content {
  grid-column-start: 1;
  grid-row-start: 1
}
.collapse > input[type="checkbox"],
.collapse > input[type="radio"] {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  opacity: 0
}
:where(.collapse > input[type="checkbox"]),
:where(.collapse > input[type="radio"]) {
  height: 100%;
  width: 100%;
  z-index: 1
}
.collapse-content {
  visibility: hidden;
  grid-column-start: 1;
  grid-row-start: 2;
  min-height: 0px;
  transition: visibility 0.2s;
  transition: padding 0.2s ease-out,
    background-color 0.2s ease-out;
  padding-left: 1rem;
  padding-right: 1rem;
  cursor: unset
}
.collapse[open] {
  grid-template-rows: max-content 1fr
}
.collapse[open] > .collapse-content {
  visibility: visible;
  min-height: -moz-fit-content;
  min-height: fit-content
}
.dropdown {
  position: relative;
  display: inline-block
}
.dropdown > *:not(summary):focus {
  outline: 2px solid transparent;
  outline-offset: 2px
}
.dropdown .dropdown-content {
  position: absolute
}
.dropdown:is(:not(details)) .dropdown-content {
  visibility: hidden;
  opacity: 0;
  transform-origin: top;
  --tw-scale-x: .95;
  --tw-scale-y: .95;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  transition-duration: 200ms
}
.dropdown:focus-within .dropdown-content {
  visibility: visible;
  opacity: 1
}
@media (hover: hover) {
  .btn:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--g-200) calc(var(--tw-border-opacity) * 100%), transparent);
      --tw-bg-opacity: 1;
      background-color: color-mix(in srgb, var(--g-200) calc(var(--tw-bg-opacity) * 100%), transparent)
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn:hover {
          background-color: color-mix(
                in oklab,
                color-mix(in srgb, var(--btn-color, var(--g-100)) calc(var(--tw-bg-opacity, 1) * 100%), transparent) 90%,
                black
              );
          border-color: color-mix(
                in oklab,
                color-mix(in srgb, var(--btn-color, var(--g-100)) calc(var(--tw-border-opacity, 1) * 100%), transparent) 90%,
                black
              )
        }
  }
  @supports not (color: oklch(0% 0 0)) {
    .btn:hover {
          background-color: var(--btn-color, var(--g-100));
          border-color: var(--btn-color, var(--g-100))
        }
  }
  .btn-ghost:hover {
      border-color: transparent
    }
  @supports (color: oklch(0% 0 0)) {
    .btn-ghost:hover {
          background-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
        }
  }
  .btn-outline:hover {
      --tw-border-opacity: 1;
      border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
      --tw-bg-opacity: 1;
      background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--g-0) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  .btn-outline.btn-primary:hover {
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn-outline.btn-primary:hover {
          background-color: color-mix(in oklab, var(--c-primary) 90%, black);
          border-color: color-mix(in oklab, var(--c-primary) 90%, black)
        }
  }
  .btn-outline.btn-success:hover {
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--c-success-ink) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn-outline.btn-success:hover {
          background-color: color-mix(in oklab, var(--c-success) 90%, black);
          border-color: color-mix(in oklab, var(--c-success) 90%, black)
        }
  }
  .btn-outline.btn-warning:hover {
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn-outline.btn-warning:hover {
          background-color: color-mix(in oklab, var(--c-warning) 90%, black);
          border-color: color-mix(in oklab, var(--c-warning) 90%, black)
        }
  }
  .btn-outline.btn-error:hover {
      --tw-text-opacity: 1;
      color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn-outline.btn-error:hover {
          background-color: color-mix(in oklab, var(--c-error) 90%, black);
          border-color: color-mix(in oklab, var(--c-error) 90%, black)
        }
  }
  .btn-disabled:hover,
  .btn[disabled]:hover,
  .btn:disabled:hover {
      --tw-border-opacity: 0;
      background-color: color-mix(in srgb, var(--c-neutral) calc(var(--tw-bg-opacity) * 100%), transparent);
      --tw-bg-opacity: 0.2;
      color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
      --tw-text-opacity: 0.2
    }
  @supports (color: color-mix(in oklab, black, black)) {
    .btn:is(input[type="checkbox"]:checked):hover,
    .btn:is(input[type="radio"]:checked):hover {
          background-color: color-mix(in oklab, var(--c-primary) 90%, black);
          border-color: color-mix(in oklab, var(--c-primary) 90%, black)
        }
  }
  :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover,
  :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
      cursor: pointer;
      outline: 2px solid transparent;
      outline-offset: 2px
    }
  @supports (color: oklch(0% 0 0)) {
    :where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(.active, .btn):hover,
    :where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(.active, .btn):hover {
          background-color: color-mix(in srgb, var(--g-900) calc(0.1 * 100%), transparent)
        }
  }
  .tab[disabled],
  .tab[disabled]:hover {
      cursor: not-allowed;
      color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
      --tw-text-opacity: 0.2
    }
}
.dropdown:is(details) summary::-webkit-details-marker {
  display: none
}
.footer {
  display: grid;
  width: 100%;
  grid-auto-flow: row;
  place-items: start;
  -moz-column-gap: 1rem;
       column-gap: 1rem;
  row-gap: 2.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem
}
.footer > * {
  display: grid;
  place-items: start;
  gap: 0.5rem
}
@media (min-width: 48rem) {
  .footer {
      grid-auto-flow: column
    }
}
.form-control {
  display: flex;
  flex-direction: column
}
.label {
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: space-between;
  padding-left: 0.25rem;
  padding-right: 0.25rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem
}
.input {
  flex-shrink: 1;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  height: 3rem;
  padding-left: 1rem;
  padding-right: 1rem;
  font-size: 1rem;
  line-height: 2;
  line-height: 1.5rem;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.input[type="number"]::-webkit-inner-spin-button {
  margin-top: -1rem;
  margin-bottom: -1rem;
  margin-inline-end: -1rem
}
.input-xs[type="number"]::-webkit-inner-spin-button {
  margin-top: -0.25rem;
  margin-bottom: -0.25rem;
  margin-inline-end: -0px
}
.input-sm[type="number"]::-webkit-inner-spin-button {
  margin-top: 0px;
  margin-bottom: 0px;
  margin-inline-end: -0px
}
.join {
  display: inline-flex;
  align-items: stretch;
  border-radius: var(--radius)
}
.join :where(.join-item) {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  border-end-start-radius: 0;
  border-start-start-radius: 0
}
.join .join-item:not(:first-child):not(:last-child),
.join *:not(:first-child):not(:last-child) .join-item {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  border-end-start-radius: 0;
  border-start-start-radius: 0
}
.join .join-item:first-child:not(:last-child),
.join *:first-child:not(:last-child) .join-item {
  border-start-end-radius: 0;
  border-end-end-radius: 0
}
.join .dropdown .join-item:first-child:not(:last-child),
.join *:first-child:not(:last-child) .dropdown .join-item {
  border-start-end-radius: inherit;
  border-end-end-radius: inherit
}
.join :where(.join-item:first-child:not(:last-child)),
.join :where(*:first-child:not(:last-child) .join-item) {
  border-end-start-radius: inherit;
  border-start-start-radius: inherit
}
.join .join-item:last-child:not(:first-child),
.join *:last-child:not(:first-child) .join-item {
  border-end-start-radius: 0;
  border-start-start-radius: 0
}
.join :where(.join-item:last-child:not(:first-child)),
.join :where(*:last-child:not(:first-child) .join-item) {
  border-start-end-radius: inherit;
  border-end-end-radius: inherit
}
@supports not selector(:has(*)) {
  :where(.join *) {
      border-radius: inherit
    }
}
@supports selector(:has(*)) {
  :where(.join *:has(.join-item)) {
      border-radius: inherit
    }
}
.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.2;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent);
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  border-bottom-width: 2px;
  min-height: 2.2em;
  min-width: 2.2em
}
.link {
  cursor: pointer;
  text-decoration-line: underline
}
.menu {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  font-size: 0.875rem;
  line-height: 1.25rem;
  padding: 0.5rem
}
.menu :where(li ul) {
  position: relative;
  white-space: nowrap;
  margin-inline-start: 1rem;
  padding-inline-start: 0.5rem
}
.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)),
.menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
  display: grid;
  grid-auto-flow: column;
  align-content: flex-start;
  align-items: center;
  gap: 0.5rem;
  grid-auto-columns: minmax(auto, max-content) auto max-content;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none
}
.menu li.disabled {
  cursor: not-allowed;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  color: color-mix(in srgb, var(--g-900) calc(0.3 * 100%), transparent)
}
:where(.menu li) {
  position: relative;
  display: flex;
  flex-shrink: 0;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: stretch
}
:where(.menu li) .badge {
  justify-self: end
}
.navbar {
  display: flex;
  align-items: center;
  padding: var(--navbar-padding, 0.5rem);
  min-height: 4rem;
  width: 100%
}
:where(.navbar > *:not(script, style)) {
  display: inline-flex;
  align-items: center
}
.progress {
  position: relative;
  width: 100%;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  overflow: hidden;
  height: 0.5rem;
  border-radius: var(--radius);
  background-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.radio {
  flex-shrink: 0;
  --chkbg: var(--g-900);
  height: 1.5rem;
  width: 1.5rem;
  cursor: pointer;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border-radius: 9999px;
  border-width: 1px;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.2
}
.range {
  height: 1.5rem;
  width: 100%;
  cursor: pointer;
  -moz-appearance: none;
       appearance: none;
  -webkit-appearance: none;
  --range-shdw: var(--g-900);
  overflow: hidden;
  border-radius: var(--radius);
  background-color: transparent
}
.range:focus {
  outline: none
}
.select {
  display: inline-flex;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  height: 3rem;
  min-height: 3rem;
  padding-inline-start: 1rem;
  padding-inline-end: 2.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 2;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 20px) calc(1px + 50%),
    calc(100% - 16.1px) calc(1px + 50%);
  background-size: 4px 4px,
    4px 4px;
  background-repeat: no-repeat
}
.select[multiple] {
  height: auto
}
.stats {
  display: inline-grid;
  border-radius: var(--radius);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
:where(.stats) {
  grid-auto-flow: column;
  overflow-x: auto
}
.stat {
  display: inline-grid;
  width: 100%;
  grid-template-columns: repeat(1, 1fr);
  -moz-column-gap: 1rem;
       column-gap: 1rem;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.1;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
  padding-top: 1rem;
  padding-bottom: 1rem
}
.stat-title {
  grid-column-start: 1;
  white-space: nowrap;
  color: color-mix(in srgb, var(--g-900) calc(0.6 * 100%), transparent)
}
.stat-value {
  grid-column-start: 1;
  white-space: nowrap;
  font-size: 2.25rem;
  line-height: 2.5rem;
  font-weight: 800
}
.swap {
  position: relative;
  display: inline-grid;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  place-content: center;
  cursor: pointer
}
.swap > * {
  grid-column-start: 1;
  grid-row-start: 1;
  transition-duration: 300ms;
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  transition-property: transform, opacity
}
.swap input {
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none
}
.tab {
  position: relative;
  grid-row-start: 1;
  display: inline-flex;
  height: 2rem;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 2;
  --tab-padding: 1rem;
  --tw-text-opacity: 0.5;
  --tab-color: var(--g-900);
  --tab-bg: var(--g-0);
  --tab-border-color: var(--g-200);
  color: var(--tab-color);
  padding-inline-start: var(--tab-padding, 1rem);
  padding-inline-end: var(--tab-padding, 1rem)
}
.tab:is(input[type="radio"]) {
  width: auto;
  border-bottom-right-radius: 0px;
  border-bottom-left-radius: 0px
}
.tab:is(input[type="radio"]):after {
  --tw-content: attr(aria-label);
  content: var(--tw-content)
}
.tab:not(input):empty {
  cursor: default;
  grid-column-start: span 9999
}
.table {
  position: relative;
  width: 100%;
  border-radius: var(--radius);
  text-align: left;
  font-size: 0.875rem;
  line-height: 1.25rem
}
.textarea {
  /* grows with its text between ~3 and ~14 lines, then scrolls (user 2026-10-26); `lh` reads the rule's own
     line-height, --s2 its padding. Outside Chromium `field-sizing` is unknown and `rows` sizes it as before. */
  field-sizing: content;
  min-height: calc(3lh + 2 * var(--s2));
  max-height: calc(14lh + 2 * var(--s2));
  flex-shrink: 1;
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 2;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.toggle {
  flex-shrink: 0;
  --tglbg: var(--g-0);
  --handleoffset: 1.5rem;
  --handleoffsetcalculator: calc(var(--handleoffset) * -1);
  --togglehandleborder: 0 0;
  height: 1.5rem;
  width: 3rem;
  cursor: pointer;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  border-radius: var(--radius);
  border-width: 1px;
  border-color: currentColor;
  background-color: currentColor;
  color: color-mix(in srgb, var(--g-900) calc(0.5 * 100%), transparent);
  transition: background,
    box-shadow var(--animation-input, 0.2s) ease-out;
  box-shadow: var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset,
    0 0 0 2px var(--tglbg) inset,
    var(--togglehandleborder)
}
.alert-info {
  border-color: color-mix(in srgb, var(--c-info) calc(0.2 * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-info-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  --alert-bg: var(--c-info);
  --alert-bg-mix: var(--g-0)
}
.alert-success {
  border-color: color-mix(in srgb, var(--c-success) calc(0.2 * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-success-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  --alert-bg: var(--c-success);
  --alert-bg-mix: var(--g-0)
}
.alert-warning {
  border-color: color-mix(in srgb, var(--c-warning) calc(0.2 * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  --alert-bg: var(--c-warning);
  --alert-bg-mix: var(--g-0)
}
.alert-error {
  border-color: color-mix(in srgb, var(--c-error) calc(0.2 * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  --alert-bg: var(--c-error);
  --alert-bg-mix: var(--g-0)
}
.badge-primary {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-warning {
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-error {
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-error) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-ghost {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-outline {
  border-color: currentColor;
  --tw-border-opacity: 0.5;
  background-color: transparent;
  color: currentColor
}
.badge-outline.badge-primary {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-outline.badge-warning {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning) calc(var(--tw-text-opacity) * 100%), transparent)
}
.badge-outline.badge-error {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error) calc(var(--tw-text-opacity) * 100%), transparent)
}
@media (prefers-reduced-motion: no-preference) {
  .btn {}
}
.btn:active:hover,
.btn:active:focus {
  transform: scale(var(--btn-focus-scale, 0.97))
}
@supports not (color: oklch(0% 0 0)) {
  .btn {
      background-color: var(--btn-color, var(--g-100));
      border-color: var(--btn-color, var(--g-100))
    }
  .btn-primary {
      --btn-color: var(--c-primary)
    }
  .btn-neutral {
      --btn-color: var(--c-neutral)
    }
  .btn-success {
      --btn-color: var(--c-success)
    }
  .btn-warning {
      --btn-color: var(--c-warning)
    }
  .btn-error {
      --btn-color: var(--c-error)
    }
}
@supports (color: color-mix(in oklab, black, black)) {
  .btn-active {
      background-color: color-mix(
            in oklab,
            color-mix(in srgb, var(--btn-color, var(--g-200)) calc(var(--tw-bg-opacity, 1) * 100%), transparent) 90%,
            black
          );
      border-color: color-mix(
            in oklab,
            color-mix(in srgb, var(--btn-color, var(--g-200)) calc(var(--tw-border-opacity, 1) * 100%), transparent) 90%,
            black
          )
    }
  .btn-outline.btn-primary.btn-active {
      background-color: color-mix(in oklab, var(--c-primary) 90%, black);
      border-color: color-mix(in oklab, var(--c-primary) 90%, black)
    }
  .btn-outline.btn-success.btn-active {
      background-color: color-mix(in oklab, var(--c-success) 90%, black);
      border-color: color-mix(in oklab, var(--c-success) 90%, black)
    }
  .btn-outline.btn-warning.btn-active {
      background-color: color-mix(in oklab, var(--c-warning) 90%, black);
      border-color: color-mix(in oklab, var(--c-warning) 90%, black)
    }
  .btn-outline.btn-error.btn-active {
      background-color: color-mix(in oklab, var(--c-error) 90%, black);
      border-color: color-mix(in oklab, var(--c-error) 90%, black)
    }
}
.btn:focus-visible {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px
}
.btn-primary {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  outline-color: var(--c-primary)
}
@supports (color: oklch(0% 0 0)) {
  .btn-primary {
      --btn-color: var(--c-primary)
    }
  .btn-neutral {
      --btn-color: var(--c-neutral)
    }
  .btn-success {
      --btn-color: var(--c-success)
    }
  .btn-warning {
      --btn-color: var(--c-warning)
    }
  .btn-error {
      --btn-color: var(--c-error)
    }
}
.btn-neutral {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-neutral-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  outline-color: var(--c-neutral)
}
.btn-success {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-success-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  outline-color: var(--c-success)
}
.btn-warning {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  outline-color: var(--c-warning)
}
.btn-error {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent);
  outline-color: var(--c-error)
}
.btn-ghost {
  border-width: 1px;
  border-color: transparent;
  background-color: transparent;
  color: currentColor;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
  outline-color: currentColor
}
.btn-ghost.btn-active {
  border-color: transparent;
  background-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.btn-outline {
  border-color: currentColor;
  background-color: transparent;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
}
.btn-outline.btn-active {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-0) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-primary {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-primary.btn-active {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-success {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-success) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-success.btn-active {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-success-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-warning {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-warning.btn-active {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-error {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn-outline.btn-error.btn-active {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn.btn-disabled,
.btn[disabled],
.btn:disabled {
  --tw-border-opacity: 0;
  background-color: color-mix(in srgb, var(--c-neutral) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-bg-opacity: 0.2;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  --tw-text-opacity: 0.2
}
.btn:is(input[type="checkbox"]:checked),
.btn:is(input[type="radio"]:checked) {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.btn:is(input[type="checkbox"]:checked):focus-visible,
.btn:is(input[type="radio"]:checked):focus-visible {
  outline-color: var(--c-primary)
}
.card :where(figure:first-child) {
  overflow: hidden;
  border-start-start-radius: inherit;
  border-start-end-radius: inherit;
  border-end-start-radius: unset;
  border-end-end-radius: unset
}
.card :where(figure:last-child) {
  overflow: hidden;
  border-start-start-radius: unset;
  border-start-end-radius: unset;
  border-end-start-radius: inherit;
  border-end-end-radius: inherit
}
.card:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px
}
.card-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 600
}
.checkbox:focus {
  box-shadow: none
}
.checkbox:focus-visible {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: var(--g-900)
}
.checkbox:disabled {
  border-width: 0px;
  cursor: not-allowed;
  border-color: transparent;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  opacity: 0.2
}
.checkbox:checked,
.checkbox[aria-checked="true"] {
  background-repeat: no-repeat;
  animation: checkmark var(--animation-input, 0.2s) ease-out;
  background-color: var(--chkbg);
  background-image: linear-gradient(-45deg, transparent 65%, var(--chkbg) 65.99%),
      linear-gradient(45deg, transparent 75%, var(--chkbg) 75.99%),
      linear-gradient(-45deg, var(--chkbg) 40%, transparent 40.99%),
      linear-gradient(
        45deg,
        var(--chkbg) 30%,
        var(--chkfg) 30.99%,
        var(--chkfg) 40%,
        transparent 40.99%
      ),
      linear-gradient(-45deg, var(--chkfg) 50%, var(--chkbg) 50.99%)
}
.checkbox:indeterminate {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  background-repeat: no-repeat;
  animation: checkmark var(--animation-input, 0.2s) ease-out;
  background-image: linear-gradient(90deg, transparent 80%, var(--chkbg) 80%),
      linear-gradient(-90deg, transparent 80%, var(--chkbg) 80%),
      linear-gradient(0deg, var(--chkbg) 43%, var(--chkfg) 43%, var(--chkfg) 57%, var(--chkbg) 57%)
}
.checkbox-primary {
  --chkbg: var(--c-primary);
  --chkfg: var(--c-primary-ink);
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent)
}
.checkbox-primary:focus-visible {
  outline-color: var(--c-primary)
}
.checkbox-primary:checked,
.checkbox-primary[aria-checked="true"] {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.checkbox-warning {
  --chkbg: var(--c-warning);
  --chkfg: var(--c-warning-ink);
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-border-opacity) * 100%), transparent)
}
.checkbox-warning:focus-visible {
  outline-color: var(--c-warning)
}
.checkbox-warning:checked,
.checkbox-warning[aria-checked="true"] {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-warning-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.checkbox-error {
  --chkbg: var(--c-error);
  --chkfg: var(--c-error-ink);
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
}
.checkbox-error:focus-visible {
  outline-color: var(--c-error)
}
.checkbox-error:checked,
.checkbox-error[aria-checked="true"] {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-error) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
@keyframes checkmark {
  0% {
    background-position-y: 5px
  }

  50% {
    background-position-y: -2px
  }

  100% {
    background-position-y: 0
  }
}
details.collapse {
  width: 100%
}
details.collapse summary {
  position: relative;
  display: block;
  outline: 2px solid transparent;
  outline-offset: 2px
}
details.collapse summary::-webkit-details-marker {
  display: none
}
.collapse:focus-visible {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: var(--g-900)
}
.collapse:has(.collapse-title:focus-visible),
.collapse:has(> input[type="checkbox"]:focus-visible),
.collapse:has(> input[type="radio"]:focus-visible) {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: var(--g-900)
}
.collapse-arrow > .collapse-title:after {
  position: absolute;
  display: block;
  height: 0.5rem;
  width: 0.5rem;
  --tw-translate-y: -100%;
  --tw-rotate: 45deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  transition-duration: 150ms;
  transition-duration: 0.2s;
  top: 1.9rem;
  inset-inline-end: 1.4rem;
  content: "";
  transform-origin: 75% 75%;
  box-shadow: 2px 2px;
  pointer-events: none
}
.collapse-title {
  position: relative
}
.collapse-title,
:where(.collapse > input[type="checkbox"]),
:where(.collapse > input[type="radio"]) {
  padding: 1rem;
  padding-inline-end: 3rem;
  min-height: 3.75rem;
  transition: background-color 0.2s ease-out
}
.collapse[open] > :where(.collapse-content) {
  padding-bottom: 1rem;
  transition: padding 0.2s ease-out,
    background-color 0.2s ease-out
}
.collapse[open].collapse-arrow > .collapse-title:after {
  --tw-translate-y: -50%;
  --tw-rotate: 225deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
}
.dropdown:focus .dropdown-content,
.dropdown:focus-within .dropdown-content {
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
}
.file-input-error {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
}
.file-input-error:focus {
  outline-color: var(--c-error)
}
.file-input-error::file-selector-button {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-error) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.label-text {
  font-size: 0.875rem;
  line-height: 1.25rem;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
.label-text-alt {
  font-size: 0.75rem;
  line-height: 1rem;
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
.input input {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  background-color: transparent
}
.input input:focus {
  outline: 2px solid transparent;
  outline-offset: 2px
}
.input[list]::-webkit-calendar-picker-indicator {
  line-height: 1em
}
.input-bordered {
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.input:focus,
.input:focus-within {
  box-shadow: none;
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent);
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.input-success {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-success) calc(var(--tw-border-opacity) * 100%), transparent)
}
.input-success:focus,
.input-success:focus-within {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-success) calc(var(--tw-border-opacity) * 100%), transparent);
  outline-color: var(--c-success)
}
.input-warning {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-border-opacity) * 100%), transparent)
}
.input-warning:focus,
.input-warning:focus-within {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-warning) calc(var(--tw-border-opacity) * 100%), transparent);
  outline-color: var(--c-warning)
}
.input-error {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
}
.input-error:focus,
.input-error:focus-within {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  outline-color: var(--c-error)
}
.input:has(> input[disabled]),
.input-disabled,
.input:disabled,
.input[disabled] {
  cursor: not-allowed;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent);
  color: color-mix(in srgb, var(--g-900) calc(0.4 * 100%), transparent)
}
.input:has(> input[disabled])::-moz-placeholder,
.input-disabled::-moz-placeholder,
.input:disabled::-moz-placeholder,
.input[disabled]::-moz-placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
.input:has(> input[disabled])::placeholder,
.input-disabled::placeholder,
.input:disabled::placeholder,
.input[disabled]::placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
.input:has(> input[disabled]) > input[disabled] {
  cursor: not-allowed
}
.input::-webkit-date-and-time-value {
  text-align: inherit
}
.join > :where(*:not(:first-child)) {
  margin-top: 0px;
  margin-bottom: 0px;
  margin-inline-start: -1px
}
.join > :where(*:not(:first-child)):is(.btn) {
  margin-inline-start: calc(var(--border-btn) * -1)
}
.join-item:focus {
  isolation: isolate
}
.link-primary {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary) calc(var(--tw-text-opacity) * 100%), transparent)
}
@supports (color:color-mix(in oklab,black,black)) {
  @media (hover:hover) {
    .link-primary:hover {
          color: color-mix(in oklab,var(--c-primary) 80%,black)
        }
  }
}
.link:focus {
  outline: 2px solid transparent;
  outline-offset: 2px
}
.link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px
}
/* D2 (mobile-consistency): a link that IS a field's value (`textLink(value = true)`) is the card's one tap target — a full
   --ctl-l row below 1024 (M4), inline text from 1024. A link inside a sentence keeps the WCAG 2.5.8 inline exception. */
@media (max-width: 1023.98px) { .link.link-value { display: inline-flex; align-items: center; min-height: var(--ctl-l); } }
.loading {
  pointer-events: none;
  display: inline-block;
  aspect-ratio: 1 / 1;
  width: 1.5rem;
  background-color: currentColor;
  -webkit-mask-size: 100%;
          mask-size: 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")
}
.loading-spinner {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")
}
.loading-xs {
  width: 1rem
}
.loading-sm {
  width: 1.25rem
}
:where(.menu li:empty) {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  opacity: 0.1;
  margin: 0.5rem 1rem;
  height: 1px
}
.menu :where(li ul):before {
  position: absolute;
  bottom: 0.75rem;
  inset-inline-start: 0px;
  top: 0.75rem;
  width: 1px;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  opacity: 0.1;
  content: ""
}
.menu :where(li:not(.menu-title) > *:not(ul, details, .menu-title, .btn)),
.menu :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
  border-radius: var(--radius);
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  text-align: start;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
  transition-duration: 200ms;
  text-wrap: balance
}
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn).focus,
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):not(summary, .active, .btn):focus,
:where(.menu li:not(.menu-title, .disabled) > *:not(ul, details, .menu-title)):is(summary):not(.active, .btn):focus-visible,
:where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn).focus,
:where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):not(summary, .active, .btn):focus,
:where(.menu li:not(.menu-title, .disabled) > details > summary:not(.menu-title)):is(summary):not(.active, .btn):focus-visible {
  cursor: pointer;
  background-color: color-mix(in srgb, var(--g-900) calc(0.1 * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  outline: 2px solid transparent;
  outline-offset: 2px
}
.menu li > *:not(ul, .menu-title, details, .btn):active,
.menu li > *:not(ul, .menu-title, details, .btn).active,
.menu li > details > summary:active {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-neutral) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-neutral-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.menu :where(li > details > summary)::-webkit-details-marker {
  display: none
}
.menu :where(li > details > summary):after {
  justify-self: end;
  display: block;
  margin-top: -0.5rem;
  height: 0.5rem;
  width: 0.5rem;
  transform: rotate(45deg);
  transition-property: transform, margin-top;
  transition-duration: 0.3s;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  content: "";
  transform-origin: 75% 75%;
  box-shadow: 2px 2px;
  pointer-events: none
}
.menu :where(li > details[open] > summary):after {
  transform: rotate(225deg);
  margin-top: 0
}
.menu-title {
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  font-weight: 700;
  color: color-mix(in srgb, var(--g-900) calc(0.4 * 100%), transparent)
}
.progress::-moz-progress-bar {
  border-radius: var(--radius);
  background-color: currentColor
}
.progress-primary::-moz-progress-bar {
  border-radius: var(--radius);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.progress:indeterminate {
  --progress-color: var(--g-900);
  background-image: repeating-linear-gradient(
    90deg,
    var(--progress-color) -1%,
    var(--progress-color) 10%,
    transparent 10%,
    transparent 90%
  );
  background-size: 200%;
  background-position-x: 15%;
  animation: progress-loading 5s ease-in-out infinite
}
.progress-primary:indeterminate {
  --progress-color: var(--c-primary)
}
.progress::-webkit-progress-bar {
  border-radius: var(--radius);
  background-color: transparent
}
.progress::-webkit-progress-value {
  border-radius: var(--radius);
  background-color: currentColor
}
.progress-primary::-webkit-progress-value {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.progress:indeterminate::-moz-progress-bar {
  background-color: transparent;
  background-image: repeating-linear-gradient(
    90deg,
    var(--progress-color) -1%,
    var(--progress-color) 10%,
    transparent 10%,
    transparent 90%
  );
  background-size: 200%;
  background-position-x: 15%;
  animation: progress-loading 5s ease-in-out infinite
}
@keyframes progress-loading {
  50% {
    background-position-x: -115%
  }
}
.radio:focus {
  box-shadow: none
}
.radio:focus-visible {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: var(--g-900)
}
.radio:checked,
.radio[aria-checked="true"] {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-900) calc(var(--tw-bg-opacity) * 100%), transparent);
  background-image: none;
  animation: radiomark var(--animation-input, 0.2s) ease-out;
  box-shadow: 0 0 0 4px var(--g-0) inset,
      0 0 0 4px var(--g-0) inset
}
.radio-primary {
  --chkbg: var(--c-primary);
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent)
}
.radio-primary:focus-visible {
  outline-color: var(--c-primary)
}
.radio-primary:checked,
.radio-primary[aria-checked="true"] {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.radio-secondary {
  --chkbg: var(--c-secondary);
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-secondary) calc(var(--tw-border-opacity) * 100%), transparent)
}
.radio-secondary:focus-visible {
  outline-color: var(--c-secondary)
}
.radio-secondary:checked,
.radio-secondary[aria-checked="true"] {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-secondary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-secondary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-secondary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.radio:disabled {
  cursor: not-allowed;
  opacity: 0.2
}
@keyframes radiomark {
  0% {
    box-shadow: 0 0 0 12px var(--g-0) inset,
      0 0 0 12px var(--g-0) inset
  }

  50% {
    box-shadow: 0 0 0 3px var(--g-0) inset,
      0 0 0 3px var(--g-0) inset
  }

  100% {
    box-shadow: 0 0 0 4px var(--g-0) inset,
      0 0 0 4px var(--g-0) inset
  }
}
.range:focus-visible::-webkit-slider-thumb {
  --focus-shadow: 0 0 0 6px var(--g-0) inset, 0 0 0 2rem var(--range-shdw) inset
}
.range:focus-visible::-moz-range-thumb {
  --focus-shadow: 0 0 0 6px var(--g-0) inset, 0 0 0 2rem var(--range-shdw) inset
}
.range::-webkit-slider-runnable-track {
  height: 0.5rem;
  width: 100%;
  border-radius: var(--radius);
  background-color: color-mix(in srgb, var(--g-900) calc(0.1 * 100%), transparent)
}
.range::-moz-range-track {
  height: 0.5rem;
  width: 100%;
  border-radius: var(--radius);
  background-color: color-mix(in srgb, var(--g-900) calc(0.1 * 100%), transparent)
}
.range::-webkit-slider-thumb {
  position: relative;
  height: 1.5rem;
  width: 1.5rem;
  border-radius: var(--radius);
  border-style: none;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent);
  appearance: none;
  -webkit-appearance: none;
  top: 50%;
  color: var(--range-shdw);
  transform: translateY(-50%);
  --filler-size: 100rem;
  --filler-offset: 0.6rem;
  box-shadow: 0 0 0 3px var(--range-shdw) inset,
      var(--focus-shadow, 0 0),
      calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size)
}
.range::-moz-range-thumb {
  position: relative;
  height: 1.5rem;
  width: 1.5rem;
  border-radius: var(--radius);
  border-style: none;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-0) calc(var(--tw-bg-opacity) * 100%), transparent);
  top: 50%;
  color: var(--range-shdw);
  --filler-size: 100rem;
  --filler-offset: 0.5rem;
  box-shadow: 0 0 0 3px var(--range-shdw) inset,
      var(--focus-shadow, 0 0),
      calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size)
}
@keyframes rating-pop {
  0% {
    transform: translateY(-0.125em)
  }

  40% {
    transform: translateY(-0.125em)
  }

  100% {
    transform: translateY(0)
  }
}
.select-bordered {
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.select:focus {
  box-shadow: none;
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent);
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.select-error {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
}
.select-error:focus {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  outline-color: var(--c-error)
}
.select:disabled,
.select[disabled] {
  cursor: not-allowed;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent);
  color: color-mix(in srgb, var(--g-900) calc(0.4 * 100%), transparent)
}
.select:disabled::-moz-placeholder,
.select[disabled]::-moz-placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
.select:disabled::placeholder,
.select[disabled]::placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
.select[multiple],
.select[size].select:not([size="1"]) {
  background-image: none;
  padding-right: 1rem
}
[dir="rtl"] .select {
  background-position: calc(0% + 12px) calc(1px + 50%),
    calc(0% + 16px) calc(1px + 50%)
}
@keyframes skeleton {
  from {
    background-position: 150%
  }

  to {
    background-position: -50%
  }
}
:where(.stats) > :not([hidden]) ~ :not([hidden]) {
  --tw-divide-x-reverse: 0;
  border-right-width: calc(1px * var(--tw-divide-x-reverse));
  border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
  --tw-divide-y-reverse: 0;
  border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse)));
  border-bottom-width: calc(0px * var(--tw-divide-y-reverse))
}
[dir="rtl"] .stats > *:not([hidden]) ~ *:not([hidden]) {
  --tw-divide-x-reverse: 1
}
.tab:is(input:checked) {
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 1;
  --tw-text-opacity: 1
}
.tab:focus {
  outline: 2px solid transparent;
  outline-offset: 2px
}
.tab:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -5px
}
.tab[disabled] {
  cursor: not-allowed;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  --tw-text-opacity: 0.2
}
.table:where([dir="rtl"], [dir="rtl"] *) {
  text-align: right
}
.table :where(th, td) {
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
  vertical-align: middle
}
.table tr.active,
.table tr.active:nth-child(even),
.table-zebra tbody tr:nth-child(even) {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.table-zebra tr.active,
.table-zebra tr.active:nth-child(even) {
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-200) calc(var(--tw-bg-opacity) * 100%), transparent)
}
.table :where(thead tr,
tbody tr:not(:last-child), tbody tr:first-child:last-child) {
  border-bottom-width: 1px;
  --tw-border-opacity: 1;
  border-bottom-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent)
}
.table :where(thead, tfoot) {
  white-space: nowrap;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 700;
  color: color-mix(in srgb, var(--g-900) calc(0.6 * 100%), transparent)
}
.table :where(tfoot) {
  border-top-width: 1px;
  --tw-border-opacity: 1;
  border-top-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent)
}
.textarea-bordered {
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.textarea:focus {
  box-shadow: none;
  border-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent);
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.textarea-error {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent)
}
.textarea-error:focus {
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  outline-color: var(--c-error)
}
.textarea:disabled,
.textarea[disabled] {
  cursor: not-allowed;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-100) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--g-100) calc(var(--tw-bg-opacity) * 100%), transparent);
  color: color-mix(in srgb, var(--g-900) calc(0.4 * 100%), transparent)
}
.textarea:disabled::-moz-placeholder,
.textarea[disabled]::-moz-placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
.textarea:disabled::placeholder,
.textarea[disabled]::placeholder {
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-placeholder-opacity) * 100%), transparent);
  --tw-placeholder-opacity: 0.2
}
[dir="rtl"] .toggle {
  --handleoffsetcalculator: calc(var(--handleoffset) * 1)
}
.toggle:focus-visible {
  outline-style: solid;
  outline-width: 2px;
  outline-offset: 2px;
  outline-color: color-mix(in srgb, var(--g-900) calc(0.2 * 100%), transparent)
}
.toggle:hover {
  background-color: currentColor
}
.toggle:checked,
.toggle[aria-checked="true"] {
  background-image: none;
  --handleoffsetcalculator: var(--handleoffset);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent)
}
[dir="rtl"] .toggle:checked,
[dir="rtl"] .toggle[aria-checked="true"] {
  --handleoffsetcalculator: calc(var(--handleoffset) * -1)
}
.toggle:indeterminate {
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--g-900) calc(var(--tw-text-opacity) * 100%), transparent);
  box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
      calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
      0 0 0 2px var(--tglbg) inset
}
[dir="rtl"] .toggle:indeterminate {
  box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset,
        calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset,
        0 0 0 2px var(--tglbg) inset
}
.toggle-primary:focus-visible {
  outline-color: var(--c-primary)
}
.toggle-primary:checked,
.toggle-primary[aria-checked="true"] {
  border-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.1;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-primary) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-primary-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.toggle-error:focus-visible {
  outline-color: var(--c-error)
}
.toggle-error:checked,
.toggle-error[aria-checked="true"] {
  border-color: color-mix(in srgb, var(--c-error) calc(var(--tw-border-opacity) * 100%), transparent);
  --tw-border-opacity: 0.1;
  --tw-bg-opacity: 1;
  background-color: color-mix(in srgb, var(--c-error) calc(var(--tw-bg-opacity) * 100%), transparent);
  --tw-text-opacity: 1;
  color: color-mix(in srgb, var(--c-error-ink) calc(var(--tw-text-opacity) * 100%), transparent)
}
.toggle:disabled {
  cursor: not-allowed;
  --tw-border-opacity: 1;
  border-color: color-mix(in srgb, var(--g-900) calc(var(--tw-border-opacity) * 100%), transparent);
  background-color: transparent;
  opacity: 0.3;
  --togglehandleborder: 0 0 0 3px var(--g-900) inset,
      var(--handleoffsetcalculator) 0 0 3px var(--g-900) inset
}
.badge-xs {
  height: 0.75rem;
  font-size: 0.75rem;
  line-height: .75rem;
  padding-left: 0.313rem;
  padding-right: 0.313rem
}
.badge-sm {
  height: 1rem;
  font-size: 0.75rem;
  line-height: 1rem;
  padding-left: 0.438rem;
  padding-right: 0.438rem
}
.badge-lg {
  height: 1.5rem;
  font-size: 1rem;
  line-height: 1.5rem;
  padding-left: 0.688rem;
  padding-right: 0.688rem
}
.btn-sm {
  height: 2rem;
  min-height: 2rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  font-size: 0.875rem
}
.btn-square:where(.btn-sm) {
  height: 2rem;
  width: 2rem;
  padding: 0px
}
.btn-circle:where(.btn-sm) {
  height: 2rem;
  width: 2rem;
  border-radius: 9999px;
  padding: 0px
}
[type="checkbox"].checkbox-xs {
  height: 1rem;
  width: 1rem
}
[type="checkbox"].checkbox-sm {
  height: 1.25rem;
  width: 1.25rem
}
.input-xs {
  height: 1.5rem;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  font-size: 0.75rem;
  line-height: 1rem;
  line-height: 1.625
}
.input-sm {
  height: 2rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  font-size: 0.875rem;
  line-height: 2rem
}
.kbd-xs {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
  font-size: 0.75rem;
  line-height: 1rem;
  min-height: 1.2em;
  min-width: 1.2em
}
[type="radio"].radio-sm {
  height: 1.25rem;
  width: 1.25rem
}
.range-sm {
  height: 1.25rem
}
.range-sm::-webkit-slider-runnable-track {
  height: 0.25rem
}
.range-sm::-moz-range-track {
  height: 0.25rem
}
.range-sm::-webkit-slider-thumb {
  height: 1.25rem;
  width: 1.25rem;
  --filler-offset: 0.5rem
}
.range-sm::-moz-range-thumb {
  height: 1.25rem;
  width: 1.25rem;
  --filler-offset: 0.5rem
}
.stats-vertical {
  grid-auto-flow: row
}
.textarea-xs {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
  font-size: 0.75rem;
  line-height: 1rem;
  line-height: 1.625
}
.tooltip {
  position: relative;
  display: inline-block;
  --tooltip-offset: calc(100% + 1px + var(--tooltip-tail, 0px))
}
.tooltip:before {
  position: absolute;
  pointer-events: none;
  z-index: 1;
  content: var(--tw-content);
  --tw-content: attr(data-tip)
}
.tooltip:before {
  transform: translateX(-50%);
  top: auto;
  left: 50%;
  right: auto;
  bottom: var(--tooltip-offset)
}
.tooltip-right:before {
  transform: translateY(-50%);
  top: 50%;
  left: var(--tooltip-offset);
  right: auto;
  bottom: auto
}
.menu-sm :where(li:not(.menu-title) > *:not(ul, details, .menu-title)),
.menu-sm :where(li:not(.menu-title) > details > summary:not(.menu-title)) {
  border-radius: var(--radius);
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
  font-size: 0.875rem;
  line-height: 1.25rem
}
.menu-sm .menu-title {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem
}
.stats-vertical > :not([hidden]) ~ :not([hidden]) {
  --tw-divide-x-reverse: 0;
  border-right-width: calc(0px * var(--tw-divide-x-reverse));
  border-left-width: calc(0px * calc(1 - var(--tw-divide-x-reverse)));
  --tw-divide-y-reverse: 0;
  border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
  border-bottom-width: calc(1px * var(--tw-divide-y-reverse))
}
.stats-vertical {
  overflow-y: auto
}
.table-xs :not(thead):not(tfoot) tr {
  font-size: 0.75rem;
  line-height: 1rem
}
.table-xs :where(th, td) {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem
}
.table-sm :not(thead):not(tfoot) tr {
  font-size: 0.875rem;
  line-height: 1.25rem
}
.table-sm :where(th, td) {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem
}
.tooltip {
  position: relative;
  display: inline-block;
  text-align: center;
  --tooltip-tail: 0.1875rem;
  --tooltip-color: var(--c-neutral);
  --tooltip-text-color: var(--c-neutral-ink);
  --tooltip-tail-offset: calc(100% + 0.0625rem - var(--tooltip-tail))
}
.tooltip:before,
.tooltip:after {
  opacity: 0;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-delay: 100ms;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
}
.tooltip:after {
  position: absolute;
  content: "";
  border-style: solid;
  border-width: var(--tooltip-tail, 0);
  width: 0;
  height: 0;
  display: block
}
.tooltip:before {
  max-width: 20rem;
  white-space: normal;
  border-radius: 0.25rem;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  background-color: var(--tooltip-color);
  color: var(--tooltip-text-color);
  width: -moz-max-content;
  width: max-content
}
.tooltip:hover:before {
  opacity: 1;
  transition-delay: 75ms
}
.tooltip:hover:after {
  opacity: 1;
  transition-delay: 75ms
}
.tooltip:has(:focus-visible):after,
.tooltip:has(:focus-visible):before {
  opacity: 1;
  transition-delay: 75ms
}
.tooltip:not([data-tip]):hover:before,
.tooltip:not([data-tip]):hover:after {
  visibility: hidden;
  opacity: 0
}
.tooltip:after {
  transform: translateX(-50%);
  border-color: var(--tooltip-color) transparent transparent transparent;
  top: auto;
  left: 50%;
  right: auto;
  bottom: var(--tooltip-tail-offset)
}
.tooltip-right:after {
  transform: translateY(-50%);
  border-color: transparent var(--tooltip-color) transparent transparent;
  top: 50%;
  left: calc(var(--tooltip-tail-offset) + 0.0625rem);
  right: auto;
  bottom: auto
}
/* agenda hour grid (lab/11) — server-rendered visit calendar; Agenda.kt writes the placement classes
   (agc column, agr row, agn span, agl lane, ago now-line offset) because the CSP allows no inline style, and
   agendaGrid.ts sets --edge from data-edge. Vendor colour = the 4px left edge (the only stripe), never the fill. The card is
   the kit card as tokens.css defines it (K6, user 2026-10-21): g-0 + 1px --c-line + --shadow-rest + --radius on a --c-bg-2
   column — contrast from the ladder, no status hue on a neutral card (the soft yellow read as a warning and drowned the
   "Aguardando validação" flag). An overlap alone wears the warning fill and border. Text on g-0: --c-ink 18.4:1, --ink-3 7.3:1,
   --c-warning 7.1:1. */
.agenda .phone-only, .agenda .desk-only { min-width: 0; }
.agenda .ev { position: relative; display: flex; gap: var(--s3); padding: var(--s3) var(--s4); min-height: 88px; background: var(--g-0); border: 1px solid var(--c-line); border-left: 4px solid var(--edge, var(--g-500)); border-radius: var(--radius); box-shadow: var(--shadow-rest); color: inherit; text-decoration: none; }
.agenda .ag-day .ev { margin: var(--s1) var(--s2) 0; }
.agenda .ev-link { display: flex; gap: var(--s3); flex: 1; min-width: 0; color: inherit; text-decoration: none; }
.agenda .ev time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 48px; flex: none; }
/* the attribution dot ("the ball", user D3 2026-10-14): the user's own colour via data-swatch-color — the card's top-right corner
   at every width, the last flex item of a month chip (F7) */
.agenda .creator-dot { flex: none; width: var(--dot); height: var(--dot); border-radius: 50%; box-shadow: 0 0 0 1px var(--c-bg); }
.agenda .ev .creator-dot { position: absolute; top: var(--s1); right: var(--s1); }
/* F2c/F2f: an overlap cluster wears the warning fill and says so — grid lanes and phone card alike */
.agenda .ev.ov { border-color: var(--c-warning); border-left-color: var(--edge, var(--g-500)); background: var(--c-warning-soft); }
.agenda .ev .s.ov-note { color: var(--c-warning); }
/* F2f: the phone list's now marker between today's past and future rows (the desktop line's twin, left as it is by D3) */
.agenda .ag-day .now { height: 2px; background: var(--c-error); }
.agenda .ev .t { font-weight: 600; }
.agenda .ev .s { font-size: var(--t-label); color: var(--ink-3); }
.agenda .ev:focus-visible { outline: none; box-shadow: var(--focus); }
.agenda .ag-day h2 { background: var(--c-bg-2); font-size: var(--t-label); font-weight: 600; padding: var(--s2) var(--s4); border-bottom: 1px solid var(--c-line); display: flex; justify-content: space-between; }
.agenda .ag-day h2 span:last-child { color: var(--ink-3); font-weight: 400; }
.agenda .ag-day h2.today { color: var(--c-primary); }
.agenda .tg { display: grid; grid-template-columns: 48px repeat(7, minmax(0, 1fr)); grid-template-rows: 32px; grid-auto-rows: minmax(var(--agenda-slot), auto); background: var(--c-bg-2); border: 1px solid var(--c-line); position: relative; isolation: isolate; }
.agenda .tg.tg-1 { grid-template-columns: 48px minmax(0, 1fr); }
.agenda .tg.tg-5 { grid-template-columns: 48px repeat(5, minmax(0, 1fr)); }
.agenda .tg.tg-6 { grid-template-columns: 48px repeat(6, minmax(0, 1fr)); }
/* The grid is its own stacking context (isolation above): the cards' z (100–300, 500 on hover) stays inside it, under the sticky .agenda-shell
   (z --z-sticky), which they painted over on scroll (prod video 2026-10-23). The day row pins under the shell — the hour grid is
   desktop-only, where the shell is one size-m row (--ctl-m + its --s2 padding twice) — and outranks every card. */
.agenda .tg .dh { position: sticky; top: calc(var(--ctl-m) + 2 * var(--s2)); z-index: 600; grid-row: 1; background: var(--g-0); border-bottom: 1px solid var(--c-line); border-left: 1px solid var(--c-line); font-size: var(--t-caption); font-weight: 600; padding: var(--s2); }
.agenda .tg .dh a { color: inherit; text-decoration: none; }
.agenda .tg .dh.today { color: var(--c-primary); box-shadow: inset 0 2px 0 var(--c-primary); }
.agenda .tg .hl { grid-column: 1; font-size: var(--t-micro); color: var(--ink-3); text-align: right; padding: 2px 4px 0 0; border-top: 1px solid var(--c-line); }
.agenda .tg .cell { border-left: 1px solid var(--c-line); border-top: 1px solid var(--c-line); }
.agenda .tg .cell.half { border-top-color: color-mix(in srgb, var(--c-line) 45%, var(--c-bg-2)); }
.agenda .tg .cell.we { background: color-mix(in srgb, var(--g-200) 50%, var(--c-bg-2)); }
.agenda .tg .cell[data-slot] { cursor: pointer; }
.agenda .tg .cell[data-slot]:hover { background: var(--c-info-soft); outline: 1px dashed var(--c-accent); outline-offset: -1px; }
.agenda .tg .cell[data-slot]:hover::after { content: attr(data-label); display: block; font-size: var(--t-micro); font-weight: 600; color: var(--c-accent); padding: var(--s1) 6px; }
/* F2c (user 2026-10-14): a later start CASCADES — agd-N indents the card --agenda-cascade of the column per step and draws it on top,
   so the earlier card keeps the whole column and its text; same-row starts at that step split it side by side (agl-N of agls-N).
   A card is at least its duration tall (--agenda-slot per 30 min) and grows to its text — nothing is ever cut. The ROW grows with
   its tallest card (minmax(--agenda-slot, auto)), so a grown card never paints over the next card's title line (user 2026-10-16:
   the earlier card hid "10:00 Massimo" under its endereço); the hour axis stretches where a long endereço needs it. Only a deeper
   step still overlaps, on purpose: within a step the earlier row wins (--r), a deeper step always wins; now-line and hover win over all cards; a target slot (550) and the sticky day row (600) win over them. */
.agenda .tg .ev { --indent: calc(var(--depth, 0) * var(--agenda-cascade)); margin: 1px 3px; margin-left: calc(3px + var(--band-x, 0px) + (100% - 6px - var(--band-x, 0px)) * (var(--indent) + (1 - var(--indent)) * var(--lane, 0) / var(--lanes, 1))); width: calc((100% - 6px - var(--band-x, 0px)) * (1 - var(--indent)) / var(--lanes, 1)); align-self: start; height: auto; min-height: calc(100% - 2px); z-index: calc(100 + var(--depth, 0) * 100 - var(--r, 0)); flex-direction: column; gap: 0; padding: 3px 6px; border: 1px solid var(--c-line); border-left: 4px solid var(--edge, var(--g-500)); border-radius: var(--radius); box-shadow: var(--shadow-rest); font-size: var(--t-caption); line-height: var(--lh-tight); }
/* The overlap's warning border outranks the grid card's own (same specificity, later rule). */
.agenda .tg .ev.ov { border-color: var(--c-warning); border-left-color: var(--edge, var(--g-500)); }
/* A row that splits into lanes pays the cascade twice — --agenda-cascade off the column, then /--lanes — and the lane left at
   ~1/3 of the column wraps the endereço one word per line and grows a card ten rows past its hour (user 2026-10-14). A laned card
   takes its even share of the WHOLE column instead; only a card alone in its row pays the indent, where the earlier card's text
   really needs the room kept. The start row and the fill still say it starts later. */
.agenda .tg .ev:not(.agls-1) { --indent: 0; }
.agenda .tg .ev:is(.agd-1, .agd-2) { box-shadow: var(--shadow-float); }
/* One card stack for the hour grid and the day-card week (user 2026-10-19, "organizar a info bonita"): a small muted time
   line, the title (cliente / número) in caption weight, then the muted lines (cliente under a número; endereço · motivo/tipo).
   Everything wraps at words and nothing is cut: the card grows taller instead. A laned card at a third of the column still
   breaks a long word; hover/focus gives it the whole column (F2b below). */
.agenda :is(.tg, .wk) .ev time { display: block; min-width: 0; font-size: var(--t-micro); font-weight: 500; color: var(--ink-3); }
.agenda :is(.tg, .wk) .ev .t { font-size: var(--t-caption); line-height: var(--lh-tight); overflow-wrap: anywhere; }
.agenda :is(.tg, .wk) .ev .s { font-size: var(--t-micro); line-height: var(--lh-tight); overflow-wrap: anywhere; }
.agenda :is(.tg, .wk) .ev:has(.creator-dot) { padding-right: calc(var(--s2) + var(--dot)); }
/* F2b: hover / focus raises a narrow card (cascaded or split) over everything and gives it the whole column; a full-width card
   already shows all its text, and raised over its later cascade it would cover them for good. Never while dragging — a grown
   card would cover the drop slots (agendaGrid.ts dropSlot). The pointer raises through agendaGrid.ts `is-raised`, not :hover: it pins
   the card's narrow height first, or the wider card rewraps shorter, its rows shrink and it slides out from under the pointer — a
   flicker (user 2026-10-26). */
.agenda .tg .ev:is(.is-raised, :focus-visible):not(.is-dragging, :active):not(.agd-0.agls-1) { z-index: 500; margin-left: 3px; width: calc(100% - 6px); }
.agenda .tg .ev[draggable="true"] { cursor: grab; }
.agenda .tg .ev:hover { box-shadow: var(--shadow-float); }
.agenda .tg .ev.is-dragging { opacity: .5; }
/* The create sweep's slots and the move's drop slot paint OVER the cards in a see-through tint (user 2026-10-23: a slot under a
   card was hidden by it), even a hovered one (z 500). Never under the dragged card itself: dropSlot targets nothing over its footprint. During a sweep
   (agendaGrid.ts `is-sweeping`) the cards let the pointer through, so none raises on hover mid-sweep (F2b). */
.agenda .tg .cell.is-target { z-index: 550; background: color-mix(in srgb, var(--c-accent) 22%, transparent); outline: 2px solid var(--c-accent); outline-offset: -2px; }
.agenda.is-sweeping .tg .ev { pointer-events: none; }
/* The held block, "bloco fantasma" (user 2026-10-26, Agenda.kt gridBand): a flat light block behind the visits — z 50, under the
   cards (100+), the now-line (400) and the target slot (550) — with the orçamentista's edge as its rail, pointer-transparent so
   its slots stay clickable, sweepable and droppable. Its label is a grid item of its own in the first row, so that row grows to
   fit it; a block running at the same time takes the next rail (rail-1). A visit on N blocks (on-band-N) clears their rails
   through --band-x in the card rule above. Never a hue fill: user colours include amber, tomato and green, the status hues (M15). */
.agenda .tg { --rail-step: 10px; }
.agenda .tg .rail-1 { --rail-x: var(--rail-step); }
.agenda .tg .band { z-index: 50; align-self: stretch; margin: 1px 3px 1px calc(3px + var(--rail-x, 0px)); pointer-events: none;
  border-left: 4px solid var(--edge, var(--g-500)); border-radius: var(--radius); background: color-mix(in srgb, var(--g-500) 9%, transparent); }
.agenda .tg .band-label { z-index: 60; align-self: start; position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s1);
  min-height: 24px; margin: 1px 3px var(--s1) calc(3px + 4px + var(--rail-x, 0px)); padding: 3px calc(var(--dot) + var(--s3)) 3px var(--s2);
  font-size: var(--t-caption); line-height: var(--lh-tight); color: var(--c-ink); text-decoration: none;
  /* Opaque, the band's own tint on the grid ground: the empty slot's "+ 11:00" hover hint beneath read through it. */
  background: color-mix(in srgb, var(--g-500) 9%, var(--c-bg-2)); }
.agenda .tg .band-label > :is(time, .s) { color: var(--ink-2); }
.agenda .tg .band-label > .t { font-weight: 600; }
.agenda .tg .band-label .creator-dot { position: absolute; top: var(--s2); right: var(--s1); }
.agenda .tg .band-label[draggable="true"] { cursor: grab; }
.agenda .tg .band-label.is-dragging { opacity: .5; }
.agenda .tg .ev.on-band-1 { --band-x: var(--rail-step); }
.agenda .tg .ev.on-band-2 { --band-x: calc(2 * var(--rail-step)); }
/* The held block on the phone (Agenda.kt bandRow, user 2026-10-26 "this is ok"): one striped row, dashed, the rail on the left. */
.agenda .ag-band { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s3); min-height: var(--ctl-l);
  margin: var(--s1) var(--s2) 0; padding: var(--s2) calc(var(--s3) + var(--dot) + var(--s2)) var(--s2) var(--s3);
  border: 1px dashed var(--g-500); border-left: 4px solid var(--edge, var(--g-500)); border-radius: var(--radius);
  color: var(--c-ink); text-decoration: none; font-size: var(--t-label);
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--g-500) 14%, transparent) 0 6px, transparent 6px 12px); }
.agenda .ag-band > :is(time, .t) { font-weight: 600; }
.agenda .ag-band > .s { color: var(--ink-2); }
.agenda .ag-band .creator-dot { position: absolute; top: var(--s2); right: var(--s2); }
.agenda .tg .now { position: relative; z-index: 400; height: 2px; align-self: start; background: var(--c-error); pointer-events: none; }
.agenda .mg { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--c-line); border: 1px solid var(--c-line); }
.agenda .mgh { background: var(--c-bg-2); font-size: var(--t-caption); font-weight: 600; padding: var(--s2); text-align: center; }
/* min-height = a full cell (day number 22 + MONTH_LINES caption chips 3×19 + "+N" 18 + 4 gaps + padding): every row the same height,
   not 104 for an empty week and 114 for a full one (walk 2026-10-14) */
.agenda .mgc { background: var(--c-bg); min-height: 114px; padding: var(--s1); display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.agenda .mgc.we { background: color-mix(in srgb, var(--c-bg-2) 50%, var(--c-bg)); }
.agenda .mgd { align-self: flex-start; padding: 2px 4px; font-size: var(--t-caption); font-weight: 600; color: var(--ink-2); text-decoration: none; }
.agenda .mgc.today .mgd { color: var(--c-primary); font-weight: 700; box-shadow: inset 0 -2px 0 var(--c-primary); }
/* F7: the month chip — caption type on a soft fill of its tipo colour (the edge at low alpha), so the chips read as items. A
   row of flex items: the awaiting ring glyph (the marker legend's own; the week/day/grid cards say it in words, C2 2026-10-21),
   the text (the only part that ellipses), the attribution dot. */
.agenda .ml { display: flex; align-items: center; gap: var(--s1); padding: calc(var(--s1) / 2) var(--s1); border-left: 3px solid var(--edge, var(--g-500)); background: color-mix(in srgb, var(--edge, var(--g-500)) 12%, var(--c-bg)); color: var(--c-ink); font-size: var(--t-caption); line-height: var(--lh-tight); text-decoration: none; }
.agenda .ml .t { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.agenda .ml time { font-weight: 400; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.agenda .mgm { padding: 1px 4px; font-size: var(--t-micro); font-weight: 600; color: var(--c-primary); text-decoration: none; }
.agenda .agc-2{grid-column:2}.agenda .agc-3{grid-column:3}.agenda .agc-4{grid-column:4}
.agenda .agc-5{grid-column:5}.agenda .agc-6{grid-column:6}.agenda .agc-7{grid-column:7}.agenda .agc-8{grid-column:8}

.agenda .agr-2{grid-row-start:2;--r:2}.agenda .agr-3{grid-row-start:3;--r:3}.agenda .agr-4{grid-row-start:4;--r:4}.agenda .agr-5{grid-row-start:5;--r:5}
.agenda .agr-6{grid-row-start:6;--r:6}.agenda .agr-7{grid-row-start:7;--r:7}.agenda .agr-8{grid-row-start:8;--r:8}.agenda .agr-9{grid-row-start:9;--r:9}
.agenda .agr-10{grid-row-start:10;--r:10}.agenda .agr-11{grid-row-start:11;--r:11}.agenda .agr-12{grid-row-start:12;--r:12}.agenda .agr-13{grid-row-start:13;--r:13}
.agenda .agr-14{grid-row-start:14;--r:14}.agenda .agr-15{grid-row-start:15;--r:15}.agenda .agr-16{grid-row-start:16;--r:16}.agenda .agr-17{grid-row-start:17;--r:17}
.agenda .agr-18{grid-row-start:18;--r:18}.agenda .agr-19{grid-row-start:19;--r:19}.agenda .agr-20{grid-row-start:20;--r:20}.agenda .agr-21{grid-row-start:21;--r:21}
.agenda .agr-22{grid-row-start:22;--r:22}.agenda .agr-23{grid-row-start:23;--r:23}.agenda .agr-24{grid-row-start:24;--r:24}.agenda .agr-25{grid-row-start:25;--r:25}
.agenda .agr-26{grid-row-start:26;--r:26}.agenda .agr-27{grid-row-start:27;--r:27}.agenda .agr-28{grid-row-start:28;--r:28}.agenda .agr-29{grid-row-start:29;--r:29}
.agenda .agr-30{grid-row-start:30;--r:30}.agenda .agr-31{grid-row-start:31;--r:31}.agenda .agr-32{grid-row-start:32;--r:32}.agenda .agr-33{grid-row-start:33;--r:33}
.agenda .agr-34{grid-row-start:34;--r:34}.agenda .agr-35{grid-row-start:35;--r:35}.agenda .agr-36{grid-row-start:36;--r:36}.agenda .agr-37{grid-row-start:37;--r:37}
.agenda .agr-38{grid-row-start:38;--r:38}.agenda .agr-39{grid-row-start:39;--r:39}.agenda .agr-40{grid-row-start:40;--r:40}.agenda .agr-41{grid-row-start:41;--r:41}
.agenda .agr-42{grid-row-start:42;--r:42}.agenda .agr-43{grid-row-start:43;--r:43}.agenda .agr-44{grid-row-start:44;--r:44}.agenda .agr-45{grid-row-start:45;--r:45}
.agenda .agr-46{grid-row-start:46;--r:46}.agenda .agr-47{grid-row-start:47;--r:47}.agenda .agr-48{grid-row-start:48;--r:48}.agenda .agr-49{grid-row-start:49;--r:49}

.agenda .agn-1{grid-row-end:span 1}.agenda .agn-2{grid-row-end:span 2}.agenda .agn-3{grid-row-end:span 3}.agenda .agn-4{grid-row-end:span 4}
.agenda .agn-5{grid-row-end:span 5}.agenda .agn-6{grid-row-end:span 6}.agenda .agn-7{grid-row-end:span 7}.agenda .agn-8{grid-row-end:span 8}
.agenda .agn-9{grid-row-end:span 9}.agenda .agn-10{grid-row-end:span 10}.agenda .agn-11{grid-row-end:span 11}.agenda .agn-12{grid-row-end:span 12}
.agenda .agn-13{grid-row-end:span 13}.agenda .agn-14{grid-row-end:span 14}.agenda .agn-15{grid-row-end:span 15}.agenda .agn-16{grid-row-end:span 16}
.agenda .agn-17{grid-row-end:span 17}.agenda .agn-18{grid-row-end:span 18}.agenda .agn-19{grid-row-end:span 19}.agenda .agn-20{grid-row-end:span 20}
.agenda .agn-21{grid-row-end:span 21}.agenda .agn-22{grid-row-end:span 22}.agenda .agn-23{grid-row-end:span 23}.agenda .agn-24{grid-row-end:span 24}
.agenda .agn-25{grid-row-end:span 25}.agenda .agn-26{grid-row-end:span 26}.agenda .agn-27{grid-row-end:span 27}.agenda .agn-28{grid-row-end:span 28}
.agenda .agn-29{grid-row-end:span 29}.agenda .agn-30{grid-row-end:span 30}.agenda .agn-31{grid-row-end:span 31}.agenda .agn-32{grid-row-end:span 32}
.agenda .agn-33{grid-row-end:span 33}.agenda .agn-34{grid-row-end:span 34}.agenda .agn-35{grid-row-end:span 35}.agenda .agn-36{grid-row-end:span 36}
.agenda .agn-37{grid-row-end:span 37}.agenda .agn-38{grid-row-end:span 38}.agenda .agn-39{grid-row-end:span 39}.agenda .agn-40{grid-row-end:span 40}
.agenda .agn-41{grid-row-end:span 41}.agenda .agn-42{grid-row-end:span 42}.agenda .agn-43{grid-row-end:span 43}.agenda .agn-44{grid-row-end:span 44}
.agenda .agn-45{grid-row-end:span 45}.agenda .agn-46{grid-row-end:span 46}.agenda .agn-47{grid-row-end:span 47}.agenda .agn-48{grid-row-end:span 48}

.agenda .agl-0 { --lane: 0; } .agenda .agl-1 { --lane: 1; } .agenda .agl-2 { --lane: 2; }
.agenda .agls-1 { --lanes: 1; } .agenda .agls-2 { --lanes: 2; } .agenda .agls-3 { --lanes: 3; }
.agenda .agd-0 { --depth: 0; } .agenda .agd-1 { --depth: 1; } .agenda .agd-2 { --depth: 2; }
.agenda .ago-0{margin-top:0px}.agenda .ago-1{margin-top:4px}.agenda .ago-2{margin-top:8px}.agenda .ago-3{margin-top:12px}.agenda .ago-4{margin-top:16px}.agenda .ago-5{margin-top:20px}

/* ── lab 08 · MENU — the one dropdown (filters, row kebab, later the unidade and section switchers) ──
 * `details.menu` outranks the DaisyUI compat `.menu` list rules above (the sidebar and a few lists still emit
 * `ul.menu`; they go with their lanes). The panel base (`.menu-panel`) is in section 1. */
/* `:where` keeps the anchor at zero specificity: a caller that places the menu (`absolute top-1 right-1`, the board kebab) wins. */
:where(details.menu) { position: relative; }
details.menu { display: inline-block; padding: 0; font-size: var(--t-label); line-height: normal; }
.menu > summary { list-style: none; display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--ctl); height: var(--ctl);
  padding: 0 var(--s3); border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--c-bg); cursor: pointer; font-size: var(--t-label); white-space: nowrap; }
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary::after { content: ""; width: 8px; height: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg) translateY(-2px); margin-left: auto; opacity: .7; }
.menu > summary:hover { border-color: var(--g-300); }
.menu > summary:focus-visible { outline: none; box-shadow: var(--focus); }
.menu[open] > summary { border-color: var(--c-primary); }
.menu.is-block, .menu.is-block > summary { display: flex; width: 100%; }
.menu.is-block > summary > [data-menu-label] { overflow: hidden; text-overflow: ellipsis; }
/* kebab: a bare glyph, S on desktop rows, L on the phone; is-bordered is the header icon */
.menu.is-kebab > summary { width: var(--ctl-l); height: var(--ctl-l); min-height: var(--ctl-l); padding: 0; justify-content: center; border-color: transparent; background: transparent; }
.menu.is-kebab > summary::after { display: none; }
.menu.is-kebab > summary:hover { background: var(--g-50); }
.menu.is-kebab.is-bordered > summary { border-color: var(--c-line); }
ul.menu-panel { list-style: none; margin: 0; }
.menu-panel li { display: block; padding: 0; }
.menu-panel form { margin: 0; }
details.menu .menu-panel li > *:active { background: var(--g-100); color: var(--c-ink); }
.menu-panel .menu-disabled :is(a, button) { color: var(--g-500); cursor: not-allowed; }
.menu-panel .menu-field { flex-direction: column; align-items: stretch; gap: var(--s1); height: auto; padding: var(--s2) var(--s3); font-weight: 400; }
.menu-panel .menu-field:hover { background: transparent; }
.menu-panel .menu-field input { width: 100%; height: var(--ctl); min-height: var(--ctl); }
@media (min-width: 1024px) {
  .menu.is-kebab > summary { width: var(--ctl-s); height: var(--ctl-s); min-height: var(--ctl-s); }
  .menu.is-end > .menu-panel { left: auto; right: 0; }
  /* The same spot (under the trigger, start- or end-aligned, at least as wide), but fixed and anchored: an absolute panel
     wider than its trigger widens the details' scroll box (layoutFit.spec.ts), a fixed one belongs to the viewport, and
     the anchor keeps it on the trigger while the page scrolls. Without anchor-scope every menu would share one name, so
     those browsers keep the absolute panel above. */
  @supports (anchor-name: --a) and (anchor-scope: --a) {
    details.menu { anchor-scope: --menu; }
    details.menu > summary { anchor-name: --menu; }
    details.menu > .menu-panel { position: fixed; position-anchor: --menu; top: calc(anchor(bottom) + 4px); left: anchor(left); min-width: anchor-size(width); position-try-fallbacks: flip-block; }
    details.menu.is-end > .menu-panel { left: auto; right: anchor(right); }
  }
}
@media (max-width: 1023.98px) {
  /* bottom sheet over a scrim, above the z-50 bars; still a details, so no JS owns the open state */
  .menu[open]::before { content: ""; position: fixed; inset: 0; z-index: calc(var(--z-dialog) + 4); background: var(--scrim); }
  .menu[open] > .menu-panel { z-index: calc(var(--z-dialog) + 5); }
  body:has(.menu[open]) .fab, body:has(.menu[open]) .back-to-top { visibility: hidden; }
}
/* ===== lab 09/10 · form rail foot, phone section line, error dot, Cancelar · Salvar bar ===== */
/* One <form> holds [section line][rail][column]. From lg the rail is sticky and its foot (.form-rail-actions) is the
   Cancelar · Salvar pair; below lg the rail dissolves (display: contents) so that same pair becomes a flex item the
   column's `order` places last — the sticky bar. One set of buttons, so every `form button[type=submit]` finds one. */
.form-dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--c-error); }
.form-line { position: sticky; top: var(--mobile-topbar-live-strip, 0px); z-index: var(--z-sticky); background: var(--c-bg-2); padding: var(--s2) 0; }
.form-line > details { position: relative; }
/* The sticky line is its own stacking context: lift it while its sheet is open, or the sticky Cancelar · Salvar paints over the sheet. */
.form-line:has(> details[open]) { z-index: calc(var(--z-dialog) + 5); }
.form-line summary { list-style: none; display: flex; align-items: center; gap: var(--s2); width: 100%; min-height: var(--ctl); padding: 0 var(--s3);
  border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--c-bg); cursor: pointer; font-size: var(--t-label); }
.form-line summary::-webkit-details-marker { display: none; }
.form-line summary::after { content: ""; width: 8px; height: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px); margin-left: auto; opacity: .7; }
.form-line details[open] > summary { border-color: var(--c-primary); }
.form-line-title { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.form-line-pos { font-size: var(--t-caption); color: var(--ink-3); white-space: nowrap; }
.form-line .menu-panel a { justify-content: space-between; }
.form-line .menu-panel a[aria-current="true"] { font-weight: 600; color: var(--c-primary); }
.form-rail-actions { margin-top: var(--s4); }
/* The 12rem rail's pair (is-fill) shares the rail's width; sized by content, a pair too long for one line
   ("Cancelar · Criar cópia") wraps to two full-width buttons instead of clipping. Below lg it is the bar's equal halves. */
@media (min-width: 1024px) { .form-rail-actions > .actions.is-fill > .btn { flex-basis: auto; } }
@media (max-width: 1023.98px) {
  .form-layout { display: flex; flex-direction: column; gap: var(--s4); }
  .form-layout > .form-rail { display: contents; }
  .form-layout > .form-rail > :not(.form-rail-actions) { display: none; }
  .form-layout > .form-rail > .form-rail-actions { order: 2; margin-top: 0; }
  .form-layout > .form-column { order: 1; }
  .form-layout .form-section-card:not([data-section-on]):not([data-section-free]) { display: none; }
}
/* agenda day columns (lab/11 .week) — the serviço week: one column per day, a stack of cards in time order, "+ Novo" at the foot. */
.agenda .wk { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--c-line); border: 1px solid var(--c-line); }
.agenda .wk.wk-1 { grid-template-columns: minmax(0, 1fr); }
.agenda .wk.wk-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.agenda .wk.wk-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.agenda .wk-day { background: var(--c-bg-2); min-height: 360px; display: flex; flex-direction: column; min-width: 0; }
.agenda .wk-day.we { background: color-mix(in srgb, var(--g-200) 50%, var(--c-bg-2)); }
.agenda .wk-day h2 { font-size: var(--t-caption); font-weight: 600; padding: var(--s2); border-bottom: 1px solid var(--c-line); background: var(--g-0); display: flex; justify-content: space-between; gap: var(--s2); }
.agenda .wk-day h2 a { color: inherit; text-decoration: none; }
.agenda .wk-day h2 span { color: var(--ink-3); font-weight: 400; }
.agenda .wk-day h2.today { color: var(--c-primary); box-shadow: inset 0 2px 0 var(--c-primary); }
.agenda .wk .ev { flex-direction: column; gap: 2px; margin: var(--s1) var(--s1) 0; padding: var(--s2); min-height: 0; font-size: var(--t-caption); }
/* The week card's lines wrap like the hour grid's (the ellipsis hid the cliente behind the street, user 2026-10-19). */
.agenda .wk .ev .s.cont { color: var(--ink-3); }
.agenda .wk .ev:hover { box-shadow: var(--shadow-float); }
.agenda .wk .ev[draggable="true"] { cursor: grab; }
.agenda .wk .ev.is-dragging { opacity: .5; }
.agenda .wk .add { margin-top: auto; padding: var(--s2); font-size: var(--t-caption); color: var(--ink-3); text-align: center; text-decoration: none; border-top: 1px dashed var(--c-line); }
.agenda .wk .add:hover { color: var(--c-primary); background: var(--c-info-soft); }
/* ── lab 08 · UNIDADE SWITCHER (D4, O15) — its own row under the brand (lg) and the top bar title (phone) open the kit menu ──
 * The top bar's trigger is the page title: it drops the control border and takes the bar's ink. The sidebar's
 * (`.unidade-switcher-block`, Sidebar.kt) is a captioned, solid, borderless chip under the brand row: beside the logo it
 * read as one control with two arrows, and bordered it read as a second search box (user 2026-10-13). So the header
 * has one chevron-down and one collapse arrow on different rows, and the search input stays its only bordered box.
 * The panel and the phone sheet are the menu's own (section MENU above). */
details.unidade-switcher { display: block; flex: 1; min-width: 0; }
.unidade-switcher > summary { display: flex; width: 100%; height: auto; min-height: var(--ctl); padding: 0; border: 0; background: transparent; color: inherit; }
/* with no summary padding the rotated chevron's corner pokes ~3px past the box (layoutFit.spec.ts) */
.unidade-switcher > summary::after { margin-right: var(--s1); }
.unidade-switcher > .menu-panel { color: var(--c-ink); }
.unidade-switcher-scope { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* the chip: the bar's ink at 20% (the logo tile's step, above the search input's 10%), a step up on hover and open */
.sidebar-shell .unidade-switcher > summary, .kit-brand-specimen .unidade-switcher > summary { height: var(--ctl); padding: 0 var(--s3); border-radius: var(--radius);
  background: color-mix(in srgb, var(--c-primary-ink) 20%, transparent); }
.sidebar-shell .unidade-switcher > summary:hover, .kit-brand-specimen .unidade-switcher > summary:hover,
.sidebar-shell .unidade-switcher[open] > summary, .kit-brand-specimen .unidade-switcher[open] > summary { background: color-mix(in srgb, var(--c-primary-ink) 30%, transparent); }
/* the Cancelar · Aplicar foot (D4b): kit buttons (MENU's row rule is `button:not(.btn)`, so they keep the kit look; the
   row, actionRow S, owns their height). It sticks to the panel's bottom edge, so with many unidades the boxes scroll
   under it: sticky stops at the scroller's padding, so the row reaches through it (--panel-pad-end mirrors the panel's
   padding-bottom, MENU section 1) and pads its own buttons by the same amount. */
.unidade-switcher .menu-panel .actions { --panel-pad-end: var(--s1); position: sticky; bottom: calc(-1 * var(--panel-pad-end));
  justify-content: flex-end; margin-bottom: calc(-1 * var(--panel-pad-end));
  padding: var(--s2) var(--s1) calc(var(--s1) + var(--panel-pad-end)); background: var(--c-bg); }
@media (max-width: 1023.98px) {
  .unidade-switcher .menu-panel .actions { --panel-pad-end: calc(var(--s2) + var(--mobile-chrome-bottom-strip)); }
}
/* the 5rem icon rail has no room for the names and clips the panel: expand the rail to switch (caption and chip go together) */
html[data-sidebar-collapsed] .sidebar-shell .unidade-switcher-block { display: none; }
/* the open sheet must paint over the bottom bar, which shares the top bar's z tier and comes later */
.mobile-topbar:has(.unidade-switcher[open]) { z-index: calc(var(--z-dialog) + 5); }
/* from lg the panel hangs over the content; the aside is sticky (its own stacking context at z auto), so lift it while
   open or positioned content painted later covers it. The panel is fixed at its static position (auto offsets: right
   under the trigger, the same spot `absolute` gave it): an absolute panel wider than the 88px trigger widens the
   details' scroll box (layoutFit.spec.ts), a fixed one belongs to the viewport. The aside is pinned at top 0, so the
   trigger never scrolls away from it. */
@media (min-width: 1024px) {
  .sidebar-shell > aside:has(.unidade-switcher[open]) { z-index: var(--z-drawer); }
  /* at least the trigger's width (the sidebar minus the brand block's p-4 gutters); as tall as its rows up to the
     sheet's viewport share, so five unidades, both picks and the foot show without a scrollbar */
  .sidebar-shell .unidade-switcher > .menu-panel { position: fixed; top: auto; left: auto; margin-top: 4px;
    min-width: calc(var(--w-sidebar) - 2 * var(--s4)); max-height: 70dvh; }
}
/* a write blocked until one unidade is picked points at the switcher (the banner is `.unidade-pick-required`) */
body:has(.unidade-pick-required) .unidade-switcher > summary { outline: 2px solid var(--c-warning-soft); outline-offset: 2px;
  animation: unidade-filter-attention 1.6s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) {
  body:has(.unidade-pick-required) .unidade-switcher > summary { animation: none; }
}
/* ── lab 07 · DATE PICKER D+ (DatePicker.kt dateField, datePicker.ts) ──
 * Picker only (user 2026-10-20: "we dont type dates"): the kit menu's summary IS the field — the shown date (or the
 * placeholder) and a calendar icon, a click anywhere on it opens the panel (lab 08) as the month popover from lg and
 * the bottom sheet below it. Step 2 is the day's hours: busy ones struck through, the selected one filled.
 * `.menu-panel button` styles every button in a panel as a menu row; the day and hour buttons undo that here. */
.date-menu { display: block; }
/* The trigger wears the `.input` look (border, radius, control height); (0,2,0) beats MENU's `.menu > summary` (0,1,1).
   The disabled field is the same shape as a disabled `button`. */
.date-field .date-trigger { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: var(--s2); height: var(--ctl); min-height: var(--ctl);
  padding: 0 var(--s3) 0 var(--s4); border: 1px solid color-mix(in srgb, var(--g-900) 20%, transparent); border-radius: var(--radius); background: var(--c-bg);
  font-size: var(--t-body); color: var(--c-ink); text-align: left; cursor: pointer; }
.date-field .date-trigger > svg { flex: none; color: var(--ink-3); }
.date-field .date-trigger:focus-visible { outline: none; box-shadow: var(--focus); }
.date-field .date-trigger.is-error { border-color: var(--c-error); }
.date-field .date-trigger[disabled] { color: var(--ink-3); background: var(--g-50); cursor: not-allowed; }
.date-menu[open] > .date-trigger { border-color: var(--c-primary); }
.date-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.date-text:empty::before { content: attr(data-placeholder); color: var(--ink-3); }
.date-echo { font-size: var(--t-caption); color: var(--ink-3); min-height: 1em; margin-top: var(--s1); }
/* Sized by its content, not a px width: seven `--ctl` day columns (M from lg, L on the phone sheet, where they stretch)
   plus the panel's padding — ~316px at M — so the title keeps one line; from lg the field-wide summary is the anchor,
   and MENU's `min-width: anchor-size(width)` would stretch the panel to the field, hence min-width 0 (0,3,1 > 0,2,1). */
.menu-panel.date-panel { --date-gap: 2px; width: max-content; max-width: none; padding: var(--s3); }
details.menu > .menu-panel.date-panel { min-width: 0; }
/* Both steps are the month grid's width (7 day columns), so the panel keeps its size when the hours replace the days. */
.date-panel .date-step { width: calc(7 * var(--ctl) + 6 * var(--date-gap)); }
.date-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s2); font-weight: 600; }
.date-title { flex: 1; text-align: center; }
/* every tap target in the panel reads the control scale (M4): L below 1024, the nav arrows S from it.
   (0,3,0): MENU's row rule `.menu-panel button:not(.btn)` (0,2,1) gives every panel button `width: 100%`, which made
   each arrow as wide as the panel, the title a 3-line sliver and the panel a horizontal scroller (2026-10-20). */
.menu-panel.date-panel .date-nav { flex: none; width: var(--ctl); height: var(--ctl); min-height: var(--ctl); padding: 0; justify-content: center; }
.date-days { display: grid; grid-template-columns: repeat(7, minmax(var(--ctl), 1fr)); gap: var(--date-gap); text-align: center; }
.date-days [role="row"], .date-days [role="gridcell"] { display: contents; }
.date-days [role="columnheader"] { font-size: var(--t-micro); color: var(--ink-3); padding: 4px 0; }
.date-panel .date-days button { position: relative; display: block; width: 100%; height: var(--ctl); min-height: 0; padding: 0; text-align: center; font-size: var(--t-label); }
.date-panel .date-days button.is-dim { color: var(--g-300); }
.date-panel .date-days button[aria-current="date"] { box-shadow: inset 0 0 0 1px var(--c-primary); }
.date-panel .date-days [aria-selected="true"] > button { background: var(--c-primary); color: var(--c-primary-ink); }
.date-panel .date-days button.is-busy::after { content: ""; position: absolute; left: 50%; bottom: 3px; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%; background: var(--c-warning); }
.date-times { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s1); }
.date-panel .date-times button { display: block; width: 100%; height: var(--ctl); min-height: 0; padding: 0; text-align: center; border: 1px solid var(--c-line); background: var(--c-bg); }
.date-panel .date-times button.is-busy { background: var(--g-100); color: var(--g-400); text-decoration: line-through; cursor: not-allowed; }
.date-panel .date-times button[aria-pressed="true"] { background: var(--c-primary); color: var(--c-primary-ink); border-color: var(--c-primary); }
.date-panel .date-days button:focus-visible, .date-panel .date-times button:focus-visible, .date-panel .date-nav:focus-visible { outline: none; box-shadow: var(--focus); }
.date-panel .actions { margin-top: var(--s2); flex-wrap: nowrap; gap: var(--s1); }
/* The shortcuts: one row of three outline buttons at the panel's foot, Hoje nearest the thumb. */
/* `1 1 auto`, not `1 1 0`: equal thirds gave "Próx. semana" 97px for 96px of text; from its own width each grows by the same slack. */
.date-panel .actions > .btn { flex: 1 1 auto; min-width: 0; height: var(--ctl); min-height: var(--ctl); padding-inline: var(--s2); }
@media (min-width: 1024px) {
  .menu-panel.date-panel .date-nav { width: var(--ctl-s); height: var(--ctl-s); min-height: var(--ctl-s); }
  /* The ~460px panel opened from a field mid-viewport (1280x800) fits neither below nor above it, and flip-block alone
     leaves it hanging past the bottom edge with the shortcuts out of reach: then it pins to the viewport's top, capped
     to the viewport and scrolling inside. (0,3,1) to beat MENU's anchored `details.menu > .menu-panel`. */
  .menu-panel.date-panel { max-height: calc(100dvh - 2 * var(--s3)); overflow: auto; }
  @supports (anchor-name: --a) and (anchor-scope: --a) {
    details.menu > .menu-panel.date-panel { position-try-fallbacks: flip-block, --date-pinned; }
  }
}
@position-try --date-pinned { top: var(--s3); }
@media (max-width: 1023.98px) {
  .menu-panel.date-panel { width: auto; max-height: 85dvh; overflow: auto; padding-bottom: calc(var(--s3) + var(--mobile-chrome-bottom-strip)); }
  .date-panel .date-step { width: auto; }
}
/* ── page: kit ── the /kit lab-08 specimen is the desktop sidebar: its width and its fill (Sidebar.kt, shell `.sidebar-shell > aside`) */
.kit-brand-specimen { width: var(--w-sidebar); padding: var(--s4); background: var(--c-primary); color: var(--c-primary-ink); }
/* the overlay specimen: 5rem tall so the × (top) and ✎ (bottom) circles keep 24px apart, as on a real 8rem thumbnail (axe target-size) */
.kit-overlay { position: relative; display: inline-block; align-self: flex-start; height: 5rem; padding: var(--s2) 2.5rem 0 0; }
.kit-overlay > .is-top { top: 0; right: 0; }
.kit-overlay > .is-bottom { bottom: 0; right: 0; }
.kit-fold-item { padding: var(--s2) var(--s4); }
.kit-caption { width: 10rem; }
.kit-size-caption { width: 6rem; }
.kit-top { align-items: flex-start; }
.kit-shadow { padding: var(--s4); border-radius: var(--radius); }
.kit-shadow.is-rest { box-shadow: var(--shadow-rest); }
.kit-shadow.is-raise { box-shadow: var(--shadow-raise); }
.kit-shadow.is-float { box-shadow: var(--shadow-float); }
@media (min-width: 1024px) {
  /* the sample list's tracks (KitView KIT_GRID_COLS): numero, cliente, bairro, data, valor, status, acoes */
  .kit-list-cols { grid-template-columns: minmax(0,5rem) minmax(0,1fr) minmax(0,9rem) minmax(0,7rem) minmax(0,8rem) minmax(0,7rem) minmax(0,var(--list-actions-w)); }
}
/* ── page: cliente ── */
/* The list's grid tracks (ClienteListView CLIENTE_COLS): a `<page>-list-cols` class the kit's gridCols takes (Lists.kt
   checkGridCols), worn by the header strip and every row; desktop-only, inside the 1024 block (ListTrackClassGuardTest). */
@media (min-width: 1024px) {
  .cliente-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,10rem) minmax(0,var(--list-actions-w)); }
}
/* The detail sections' empty-state CTA centres under the note: the actionRow twin of app-components.css `.empty-note + .card-actions`,
   which the old card-actions wrapper matched (KIT-GAP: kit-wide once the kit's card-actions rows move to actionRow). */
.empty-note + .actions.is-end { justify-content: center; }
/* ── page: endereco ── */
/* The set-contrato busy spinner, pinned to the viewport corner while the list re-renders (EnderecoListView). */
.endereco-busy { position: fixed; top: var(--s4); right: var(--s4); z-index: var(--z-dialog); }
/* The CEP line (EnderecoFormView cepControls): input over the lookup buttons on the phone, one row from 1024; the `actions` wrapper
   has no box so the buttons are the row's own flex items. */
.endereco-cep { width: 100%; }
.endereco-cep-row { display: flex; flex-direction: column; gap: var(--s2); }
.endereco-cep-row > .input { width: 100%; min-width: 0; }
.endereco-cep-row > .actions { display: contents; }
.endereco-cep-row .address-lookup-btn { width: 100%; white-space: nowrap; }
@media (min-width: 1024px) {
  .endereco-cep-row { flex-direction: row; }
  .endereco-cep-row > .input { flex: 1 1 0%; }
  .endereco-cep-row .address-lookup-btn { width: auto; }
}
/* Mover: the history list scrolls past 16rem; one row = checkbox + a title line over a meta line. */
.endereco-move-rows { max-height: 16rem; overflow-y: auto; }
.endereco-move-row { display: flex; align-items: flex-start; gap: var(--s2); padding: var(--s1) 0; cursor: pointer; }
.endereco-move-row > input { margin-top: 2px; }
.endereco-move-num { font-size: var(--t-label); font-weight: 600; }
.endereco-move-note { font-style: italic; }
.endereco-move-row > span { display: flex; flex-direction: column; min-width: 0; }
/* ── page: notificacao ── */
.notificacao-push { margin-bottom: var(--s4); }
.notificacao-card { background: var(--c-bg); border: 1px solid var(--c-line); }
.notificacao-card > .card-body { gap: var(--s3); padding: var(--s4); }
.notificacao-card > .card-body > a { flex: 1 1 auto; min-width: 0; }
.notificacao-card > .card-body > a:hover h3 { color: var(--c-primary); }
@media (min-width: 1024px) {
  .notificacao-push { align-items: flex-end; }
  .notificacao-card > .card-body { flex-direction: row; align-items: center; }
}
/* ── page: home ── */
/* The Hoje painel and inbox rows: each row IS the link (M22), rows divide themselves (HomeView home-list/home-row).
   No `display` here: a row rides with `stack` or `between`, which this later rule would otherwise override. */
.home-list { background: var(--c-bg); border: 1px solid var(--c-line); }
.home-row { padding: var(--s4) var(--s3); color: inherit; text-decoration: none; transition: background-color .15s; }
.home-row + .home-row { border-top: 1px solid var(--g-100); }
.home-row:hover { background: var(--g-50); }   /* the ladder's hover step; was base-200/60 */
/* The diaria card's top edge carries its state: success once confirmed, warning while owed or unavailable (after .section, so it wins). */
/* a row's first line (servico numero, inbox title) and a one-line action row: semibold, no heading weight */
.home-row-title { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }   /* a long número (8775M.2/8775.1M.2/8939M) wraps in its flex row, status beside it, instead of widening the row */
.home-row-text { font-size: var(--t-label); font-weight: 600; }
.home-row-status { text-align: right; }
.home-row .badge { flex-shrink: 0; }
.home-row > svg { flex-shrink: 0; color: var(--ink-3); }
/* The desktop tile grid (managementTiles): 4 tiles a row from 1024, 8 from 1280 (the nav it repeats is a phone bar below that).
   (0,2,0) over `.actions` (flex) and the size-l button height. */
.actions.home-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
.home-tiles > .home-tile { height: auto; flex-direction: column; gap: var(--s1); padding-block: var(--s3); }
.home-tiles > .home-tile.is-top { justify-content: flex-start; }
.home-tile > span { white-space: normal; text-align: center; font-size: var(--t-caption); line-height: var(--lh-tight); }
@media (min-width: 1024px) { .actions.home-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .actions.home-tiles { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
.home-diaria { border-top: 4px solid var(--c-success); }
.home-diaria.is-warning { border-top-color: var(--c-warning); }
/* ── page: admin ── the user form's unidade picker (UserFormView): one tile per unidade, the member box and the primary radio */
/* a user's empty name / unidade in the list: the placeholder reads quieter than a value */
.user-unset { font-style: italic; opacity: .75; }
.user-unidade { margin-top: var(--s1); }
.user-unidade-help { margin-bottom: var(--s2); font-size: var(--t-label); }
.user-unidade-row { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3); background: var(--g-100); }
.user-unidade-pick { display: flex; flex: 1 1 auto; align-items: baseline; gap: var(--s3); min-width: 0; cursor: pointer; }
.user-unidade-pick > input { flex-shrink: 0; }
.user-unidade-pick .label-text { min-width: 0; overflow-wrap: break-word; }
.user-unidade-primary { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); background: color-mix(in srgb, var(--g-0) 60%, transparent); cursor: pointer; }
.user-unidade-primary > input { flex-shrink: 0; }
.user-unidade-primary .label-text { font-size: var(--t-caption); opacity: .7; }
@media (min-width: 1024px) {
  .user-unidade-row { flex-direction: row; align-items: center; justify-content: space-between; }
  .user-unidade-pick { align-items: center; }
  .user-unidade-primary { margin-left: var(--s4); padding: 0; background: transparent; }
}
/* ── page: error ── */
/* the body: the navy page the card centres on (was bg-secondary + flex utilities) */
.error-body { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: var(--c-secondary); }
.error-detail { font-size: var(--t-caption); }
/* the errorRef: a machine string, quiet mono text (the toast's .toast-ref twin) */
.error-ref { text-align: center; font-family: var(--font-mono); font-size: var(--t-caption); color: var(--ink-3); }
.error-shell { width: 100%; max-width: 28rem; margin: 0 auto; padding: var(--s4); }
.error-shell .card { background: var(--c-bg); }
/* ── page: login ── the pre-auth card (LoginView): shell, logo, tagline and the gaps the card-body gap does not give */
/* the body: the navy page the card, the copyright line and the install hint centre on (was bg-secondary + flex utilities) */
.login-shell { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; min-height: 100dvh;
  padding: var(--s4); background: var(--c-secondary); }
.login-footer { margin-top: var(--s4); text-align: center; font-size: var(--t-caption); color: color-mix(in srgb, var(--c-secondary-ink) 60%, transparent); }
.login-install-hint { margin-top: 0; max-width: 28rem; padding-inline: var(--s4); color: color-mix(in srgb, var(--c-secondary-ink) 70%, transparent); }
.login-card { width: 100%; max-width: 28rem; background: var(--c-bg); border-top: 4px solid var(--c-primary); box-shadow: var(--shadow-rest); }
.login-card > .card-body { padding: var(--s5); }
.login-logo { display: flex; justify-content: center; margin-bottom: var(--s2); }
.login-logo img { height: 80px; }
.login-tagline { text-align: center; margin: var(--s1) 0 var(--s2); }
.login-card .alert { margin-bottom: var(--s4); }
.login-card .alert-success { box-shadow: var(--shadow-rest); }
.login-card form { margin-top: var(--s4); }
@media (min-width: 1024px) {
  .login-card > .card-body { padding: var(--s6); }
}
/* ── page: search ── the global search results (GlobalSearchResultsView) inside the sidebar panel and the phone dialog */
.search-note  { padding: var(--s3) var(--s4); }
.search-group { padding: var(--s2) var(--s4) var(--s1); }
.search-more + .search-group { margin-top: var(--s1); padding-top: var(--s3); border-top: 1px solid var(--g-100); }
.search-item  { display: flex; align-items: center; gap: var(--s3); min-height: var(--ctl-l); padding: var(--s2) var(--s4);
  font-size: var(--t-label); color: var(--c-ink); text-decoration: none; }
.search-item:hover, .search-item:focus { background: var(--g-100); }
.search-item > :not(.grow) { flex-shrink: 0; }
.search-item .grow > * { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-item b { font-weight: 600; color: var(--ink-2); }
.search-icon  { width: 16px; height: 16px; color: var(--ink-3); }
.search-more  { padding-block: var(--s1); font-size: var(--t-caption); font-weight: 600; color: var(--c-primary); }
@media (min-width: 1024px) {
  .search-item { min-height: 0; }
}
/* ── page: equipe ── */
/* The member and phone picker tiles (EquipeFormView): a filled band per row; no primitive paints a surface. */
.equipe-tile { padding: var(--s3); background: var(--g-100); }
/* A member tile: the member checkbox over the chefe radio on the phone, side by side from 1024. */
.equipe-member { display: flex; flex-direction: column; gap: var(--s2); }
@media (min-width: 1024px) {
  .equipe-member { flex-direction: row; align-items: center; justify-content: space-between; }
}
/* the tiles' labels are the tap targets; a phone another equipe holds greys out from its disabled box */
.equipe-member label, label.equipe-tile { cursor: pointer; }   /* every pointer: app.css's 48px .label-pick row applies below 1024 or on a coarse pointer */
label.equipe-tile:has(input:disabled) { cursor: not-allowed; opacity: .6; }
/* ── page: orcamento ── (DS-E E1) shapes only the orçamento pages draw and no kit renderer covers yet. */
/* KIT-GAP(alert): no alert renderer — the compat .alert centres its grid below 640px; these read left-aligned, icon first. */
.orcamento-alert { margin-bottom: var(--s4); justify-items: start; text-align: start; }
.orcamento-alert-body { display: flex; align-items: flex-start; gap: var(--s2); }
.orcamento-alert-icon { width: 20px; height: 20px; flex-shrink: 0; }
@media (min-width: 1024px) { .orcamento-alert-action { justify-self: end; } }
/* the form's zero-size implicit-submit trap: its first button, never seen or focused (OrcamentoFormView) */
.orcamento-submit-trap { position: absolute !important; width: 0 !important; height: 0 !important; overflow: hidden !important;
  padding: 0 !important; border: 0 !important; }
/* a line pulled up under its section header (the resumo table, the regiao numero) */
.orcamento-under-head { margin-top: calc(-1 * var(--s2)); margin-bottom: var(--s2); }
/* "Resumo por tipo" (infiltracoes page + detail card; scrolls sideways itself, see the F1a block): figures right-aligned, the footer a full-ink total */
.orcamento-resumo :where(th, td):not(:first-child) { text-align: right; }
.orcamento-resumo thead tr { color: var(--ink-3); }
.orcamento-resumo tfoot { font-weight: 600; color: var(--c-ink); }
/* the infiltracao card: raised on hover; head = numero + local, the valor column beside it from 1024px */
.orcamento-card { position: relative; background: var(--c-bg); border: 1px solid var(--c-line); transition: box-shadow .15s cubic-bezier(.4, 0, .2, 1); }
.orcamento-card:hover { box-shadow: var(--shadow-raise); }
.orcamento-card > .card-body { padding: var(--s4); gap: var(--s3); }
.orcamento-card-head { display: flex; flex-direction: column; gap: var(--s2); }
.orcamento-card-head > h3 { display: flex; align-items: flex-start; gap: var(--s2); min-width: 0; }
.orcamento-card-head > h3 > :first-child { margin-top: 2px; flex-shrink: 0; white-space: nowrap; color: var(--ink-3); }
.orcamento-card-head > h3 > :last-child { min-width: 0; overflow-wrap: break-word; }
.orcamento-card-head > div { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); flex-shrink: 0; }
.orcamento-card-head > div > :first-child { max-width: 100%; overflow-wrap: break-word; font-weight: 600; }
@media (min-width: 1024px) {
  .orcamento-card-head { flex-direction: row; align-items: flex-start; justify-content: space-between; }
  .orcamento-card-head > div { align-items: flex-end; }
  .orcamento-card-head > div > :first-child { white-space: nowrap; }
}
.orcamento-card-facts { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s5); font-size: var(--t-label); color: var(--ink-2); }
.orcamento-card-facts > span > :first-child { color: var(--c-ink); }
.orcamento-card-foot { justify-content: flex-end; align-items: center; margin-top: var(--s1); padding-top: var(--s3); border-top: 1px solid var(--g-100); }
.orcamento-junta-hint { font-size: var(--t-caption); text-align: right; }
.orcamento-junta-hint > span { color: var(--c-info); }
.orcamento-junta-hint > span + span { font-weight: 700; }
.orcamento-junta-hint > div { margin-top: var(--s1); }
/* KIT-GAP(field advisory): a toned line under a field, shown/hidden by conditionalFields.ts or orcamento.ts */
.orcamento-note { margin-top: var(--s2); font-size: var(--t-label); }
.orcamento-note[data-tone="error"] { color: var(--c-error); }
.orcamento-note[data-tone="info"] { color: var(--c-info); }
.orcamento-note[data-tone="warning"] { color: var(--c-warning); }
/* a help line under a hand-rolled control (the kit's helpLine is private to Forms.kt) */
.orcamento-hint { margin-top: var(--s1); }
/* the pricing-recalc spinner row: right-aligned, its height held so the grid does not jump */
.orcamento-recalc { display: flex; justify-content: flex-end; min-height: var(--s4); }
/* a saved anexo chip and its x overlay */
.orcamento-chip { position: relative; }
.orcamento-chip > .actions .btn { gap: var(--s1); }
.orcamento-chip:has(> .orcamento-chip-remove) > .actions .btn { padding-right: var(--s4); }
.orcamento-chip-remove { position: absolute; top: calc(-1 * var(--s2)); right: calc(-1 * var(--s2)); }
/* an input's unit badge (m, cm, un) joined to its right edge; infiltracao.ts toggles `hidden` on two of them */
.orcamento-unit { flex-shrink: 0; display: flex; align-items: center; padding: 0 var(--s3); border: 1px solid var(--c-line);
  background: var(--g-100); font-size: var(--t-label); font-weight: 600; }
/* ── page: orcamento · detail + infiltrações (DS-F F1a) ── the orçamento detail page's own shapes and the infiltração strips.
   Phone = base, 1024+ = desktop; the old 640/768 steps are gone (two tiers). */
/* a line in the detail page's alert slot (sent-at note, blocked-action hints, the stale-pricing alert): 16 below it, 24 from 1024 */
.orcamento-slot { margin-bottom: var(--s4); }
.orcamento-slot-list > * + * { margin-top: calc(var(--s1) / 2); }
@media (min-width: 1024px) { .orcamento-slot { margin-bottom: var(--s5); } }
.orcamento-title-extra, .contrato-title-extra { margin-top: var(--s2); }
/* a status link/flag that wraps in the header instead of overflowing it; one line from 1024 */
.badge.orcamento-badge-wrap { height: auto; max-width: 100%; white-space: normal; overflow-wrap: break-word; padding-block: var(--s1);
  text-align: center; line-height: var(--lh-tight); }
@media (min-width: 1024px) { .badge.orcamento-badge-wrap { white-space: nowrap; } }
/* the send-email recipient picker (2+ emails) */
.orcamento-email-picker { max-height: 13rem; overflow-y: auto; border: 1px solid var(--c-line); padding: var(--s1); }
.label.orcamento-email-option { justify-content: flex-start; }
.orcamento-email-option > input { margin-right: var(--s2); }
.orcamento-email-option .label-text { word-break: break-all; }
.orcamento-email-hint { margin-top: var(--s3); font-size: var(--t-label); color: var(--c-warning); }
/* the cliente card's field grid: one column on the phone, four from 1024 */
.orcamento-fields { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--s5); row-gap: var(--s4); }
.orcamento-fields > * { min-width: 0; }
@media (min-width: 1024px) { .orcamento-fields { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* a read-only value: semibold, long text wraps; `is-muted` = the "not informed" form */
.orcamento-value { font-weight: 600; overflow-wrap: break-word; }
.orcamento-value.is-muted { color: var(--ink-3); }
.orcamento-sign { color: var(--ink-3); }
.orcamento-tone-error { color: var(--c-error); }
/* a block set apart from the one above it */
.orcamento-block { margin-top: var(--s4); }
.orcamento-label-row { margin-bottom: var(--s1); }
.field-label.orcamento-label-gap { margin-bottom: var(--s2); }
/* running text inside a card: 14 px, wraps; `is-pre` keeps the author's line breaks, `is-hint` = a muted aside under a value */
.orcamento-text { font-size: var(--t-label); overflow-wrap: break-word; }
.orcamento-text.is-pre { white-space: pre-line; }
.orcamento-text.is-hint { margin-top: var(--s1); max-width: 20rem; color: var(--ink-3); }
/* the "outros orçamentos" dropdown: a data picker (numero / status / valor per row), not an actions menu */
.orcamento-btn-tight { gap: var(--s1); }
/* The trigger lives in a quarter-width grid cell: it takes the cell's width at most and ellipsizes its label, so it never runs under the next column
   (the open panel is absolute and overlays on purpose). */
.orcamento-fields .dropdown { display: block; min-width: 0; }
.orcamento-fields .dropdown > .actions { min-width: 0; }
.orcamento-fields .dropdown > .actions .btn { max-width: 100%; flex-wrap: nowrap; }
.orcamento-fields .dropdown > .actions .btn > svg { flex-shrink: 0; }
.orcamento-fields .field-label { overflow-wrap: anywhere; }
.orcamento-fields .dropdown > .actions .btn > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
ul.orcamento-vinculados { z-index: 1; width: 28rem; max-width: calc(100vw - 2rem); max-height: 20rem; flex-wrap: nowrap; overflow-y: auto;
  border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--c-bg); padding: var(--s2); box-shadow: var(--shadow-raise); }
a.orcamento-vinculado { display: grid; grid-template-columns: minmax(5rem, 1fr) 7rem minmax(6rem, auto); align-items: center; gap: var(--s3); }
.orcamento-vinculado > :first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.orcamento-vinculado > :last-child { white-space: nowrap; text-align: right; font-size: var(--t-label); color: var(--ink-3); }
@media (max-width: 1023.98px) {
  /* Phone (QA walk 2026-10-21): the panel flows in the document under its trigger instead of hanging absolute — open, it
     reached under the fixed bottom nav with one row in view. Hidden it must take no space, so `display`, not the
     dropdown's visibility fade. The número is page identity: it wraps on a line of its own, status and valor below it. */
  .orcamento-fields .dropdown > .orcamento-vinculados { display: none; position: static; width: auto; max-width: none; max-height: none; margin-top: var(--s2); }
  .orcamento-fields .dropdown:focus-within > .orcamento-vinculados { display: flex; }
  a.orcamento-vinculado { grid-template-columns: auto minmax(0, 1fr); grid-auto-flow: row; }
  .orcamento-vinculado > :first-child { grid-column: 1 / -1; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
}
/* Valores: the money strip (the 1px gap and padding ARE the hairline rules between cells, shown through the grey ground, not spacing; a column on the phone, a wrapping row from 1024) and the KPI flow */
.orcamento-money { display: flex; flex-direction: column; gap: 1px; background: var(--g-200); padding: 1px; }
.orcamento-money-cell { min-width: 0; background: var(--g-0); padding: var(--s2) var(--s3); }
.orcamento-money-value { font-size: var(--t-title); font-weight: 600; line-height: var(--lh-body); }
.orcamento-money-value.is-info { color: var(--c-info); }
.orcamento-money-value.is-error { color: var(--c-error); }
.orcamento-money-value.is-final { font-weight: 700; color: var(--c-success); }
@media (min-width: 1024px) {
  .orcamento-money { flex-direction: row; flex-wrap: wrap; align-items: stretch; }
  .orcamento-money-cell { flex: 1 1 10rem; min-width: 10rem; }
}
.orcamento-kpi-flow { display: flex; flex-wrap: wrap; align-items: flex-start; column-gap: var(--s6); row-gap: var(--s3); min-width: 0; }
.orcamento-kpi { font-weight: 600; line-height: var(--lh-body); }
.orcamento-kpi.is-nowrap { white-space: nowrap; }
.orcamento-kpi.is-error { color: var(--c-error); }
/* the payment suggestion: the KPI fields on grey behind a tag, so it never reads as an agreed figure */
/* Phone: the tag sits above the figures (beside them the nowrap KPIs ran under it); from 1024 it stands to their right. */
.orcamento-suggestion { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s2); min-width: 0; background: var(--g-100); padding: var(--s3) var(--s4); }
.orcamento-suggestion > .count-badge { flex-shrink: 0; order: -1; margin-left: 0; }
@media (min-width: 1024px) {
  .orcamento-suggestion { flex-direction: row; gap: var(--s4); }
  .orcamento-suggestion > .count-badge { order: 0; }
}
.orcamento-label-row > .count-badge { margin-left: 0; }   /* the cluster gap already spaces it */
/* the paging buttons under the infiltração cards */
.orcamento-pager { display: flex; justify-content: center; margin-top: var(--s4); }
.orcamento-pager .join { flex-wrap: wrap; }
/* the detail page's infiltração card: head = numero + local, the valor beside it from 1024; the edit link rides the foot */
.orcamento-mini { display: flex; flex-direction: column; border: 1px solid var(--c-line); padding: var(--s3); }
.orcamento-mini-head { display: flex; flex-direction: column; gap: var(--s2); }
.orcamento-mini-head > :first-child { min-width: 0; }
.orcamento-mini-title { display: flex; align-items: baseline; gap: var(--s2); min-width: 0; font-weight: 600; }
.orcamento-mini-title > :first-child { flex-shrink: 0; white-space: nowrap; color: var(--ink-3); }
.orcamento-mini-title > :last-child { min-width: 0; overflow-wrap: break-word; }
.orcamento-mini-valor { flex-shrink: 0; font-weight: 600; }
.orcamento-mini-foot { margin-top: auto; border-top: 1px solid var(--g-100); padding-top: var(--s2); }
@media (min-width: 1024px) {
  .orcamento-mini-head { flex-direction: row; align-items: flex-start; justify-content: space-between; }
  .orcamento-mini-valor { margin-left: var(--s2); text-align: right; }
}
/* Vínculos: the maintenance source (warning ground), the agendamento / contrato cards */
.orcamento-source { border: 1px solid var(--c-warning); background: var(--c-warning-soft); padding: var(--s4); }
.orcamento-source-head { flex-wrap: wrap; }
.orcamento-source-servicos { margin-top: var(--s3); border-top: 1px solid color-mix(in srgb, var(--c-warning) 30%, transparent); padding-top: var(--s3); }
.orcamento-vinculo { border: 1px solid var(--c-line); padding: var(--s4); }
.orcamento-vinculo-actions { justify-content: flex-end; margin-top: var(--s2); }
.orcamento-problema { margin-top: var(--s2); overflow-wrap: break-word; }
/* the infiltrações workspace: the section rail beside the column from 1024 */
@media (min-width: 1024px) { .orcamento-workspace { display: flex; align-items: flex-start; justify-content: flex-start; gap: var(--s5); } }
.orcamento-count { margin-top: var(--s4); font-size: var(--t-label); }
/* "Resumo por tipo" and the pricing-config tier tables scroll sideways inside their wrapper */
.orcamento-resumo, .orcamento-scroll { overflow-x: auto; }
@media (max-width: 1023.98px) {
  /* five columns in a phone card without a sideways scroll (QA walk 2026-10-21): cells pack to --s1, the headers and the
     tipo wrap, the numbers stay one piece; `.table-xs` keeps the 12 px floor */
  .orcamento-resumo .table :where(th, td) { padding-inline: var(--s1); }
  .orcamento-resumo .table :where(thead, tfoot) { white-space: normal; }
  .orcamento-resumo .table th { vertical-align: bottom; }
  .orcamento-resumo .table th:last-child { hyphens: auto; overflow-wrap: anywhere; }   /* "Produtividade/dia" has no break opportunity of its own: hyphenate by the page lang, anywhere only without a dictionary */
  .orcamento-resumo .table td { white-space: nowrap; }
  .orcamento-resumo .table td:first-child { white-space: normal; overflow-wrap: break-word; }   /* break-word, not anywhere: the tipo keeps its longest word whole */
}
/* a measure input joined to its unit badge: the input takes the width the badge leaves */
.orcamento-measure > .input { flex: 1 1 auto; min-width: 0; }
/* the photo strip (OrcamentoInfiltracaoImages) wears the kit tile family (.media-thumb*): two columns, three from 1024 where `is-wide`;
   `is-lg` tiles fill their cell instead of the kit's 160 px */
.orcamento-thumbs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); margin-top: var(--s2); }
@media (min-width: 1024px) { .orcamento-thumbs.is-wide { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.orcamento-thumb-link { display: block; }
.media-thumb-img.is-lg { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; }
.orcamento-thumb-caption { width: 100%; }
/* ── page: orcamento · list, form, config (DS-F F1b) ── the orçamento list row, the form's field states and the pricing-config tier table. */
/* the list row (OrcamentoListView): the phone card's 16 px between its head and its lines, the valor beside the número, the cliente cell's name row */
.list-primary.orcamento-primary { gap: var(--s4); }
.orcamento-valor { flex-shrink: 0; white-space: nowrap; font-weight: 600; }
.orcamento-lines { font-size: var(--t-label); line-height: var(--lh-body); }
.orcamento-meta { --gap: var(--s2); color: var(--ink-2); }   /* the `.cluster` primitive reads --gap, so no source order decides */
.orcamento-name-row { display: flex; align-items: flex-start; gap: var(--s2); min-width: 0; }
.orcamento-name-row > :first-child { min-width: 0; overflow-wrap: break-word; }
.orcamento-address { margin-top: var(--s1); font-size: var(--t-caption); }
.orcamento-value.is-ink { color: var(--c-ink); }
/* the payment-suggestions fold in the form: its own border and no outer padding (the DaisyUI collapse supplies the radius and the title/content padding) */
.orcamento-suggestions { border: 1px solid var(--c-line); padding: 0; }
/* the pricing-config tier tables: a narrow action column, the remove button at the cell's end (the wrapper scrolls via `.orcamento-scroll`, above) */
.orcamento-tier-action { width: var(--s7); }
.orcamento-tier-remove { text-align: right; }
/* ── list ── (DS-E E7) the list kit: Lists.kt + ListPage.kt. Phone = cards (base), 1024+ = the lab table (lab 01 §4,
   lab.css .table): header band, vertical rules, zebra, hover, rows 44. One breakpoint for every ListBreakpoint entry. */
/* rows container: a card stack on the phone, the table body from 1024 (#list-more stays its LAST child) */
.list-rows { display: flex; flex-direction: column; gap: var(--s3); }
/* a row: `entity-list-item` is the e2e/TS hook, this is its look; the creator strip is absolute inside it */
.list-row { position: relative; display: flex; flex-direction: column; min-height: var(--row);
  background: var(--c-bg); border: 1px solid var(--c-line); border-radius: var(--radius); }
.list-row:hover { background: var(--g-50); }
/* the row link dissolves so its cells are the row's grid items; every item may shrink below its text (no blowout) */
.list-link { display: contents; }
.list-row > *, .list-link > *, .list-primary > * { min-width: 0; }
/* right pad clears the phone ⋮: .list-actions sits --s2 in from the edge with a 48px (--s7) trigger */
.list-primary { display: flex; flex: 1 1 auto; flex-direction: column; gap: var(--s2); padding: var(--s4) calc(var(--s7) + var(--s2)) var(--s4) var(--s4); }
.list-primary :where(p, span, dd, dt, li, h3) { overflow-wrap: anywhere; }
.list-title { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--s2); font-size: var(--t-body); font-weight: 600; line-height: var(--lh-tight); }
/* A flag keeps its words together; in a narrow column it wraps under the title as a whole, never spills (pedidos # at 1024). */
.list-title > * + * { white-space: nowrap; flex-shrink: 0; }
/* the kebab, pinned top-right of the phone card (M22). No z-index: a positioned box with one is a stacking context, and
   the open sheet (`.menu[open] > .menu-panel`, z-dialog+5) was trapped in it under the fixed bottom nav (z-50) — Excluir
   unreachable (F0, 2026-10-13). At z auto the sheet and its scrim resolve against the root; the kebab still paints over
   the in-flow title, and the fixed sheet needs no lift to clear later rows. */
.list-actions { position: absolute; top: var(--s2); right: var(--s2); display: flex; justify-content: flex-end; gap: var(--s2); }
/* F1/D5 (ui-feedback 2026-10-13): the desktop face of `rowActions` — pencil + trash as icon-only `.btn-square`s in a
   `size-s` row (`--ctl-s`, the kebab's own desktop box), flush like the mockup, never wrapping inside the AÇÕES track.
   `desk-only`, so the phone keeps its kebab. */
.actions.row-actions { gap: 0; flex-wrap: nowrap; }   /* (0,2,0): `.actions` (app-components.css) sets gap/wrap later at (0,1,0) */
.row-actions > .btn { padding: 0; }                    /* (0,2,0) over `:where(.size-s) .btn`'s padding-inline; the icon centres in --ctl */
.list-cell { align-items: center; font-size: var(--t-label); color: var(--c-ink); }
.list-cell-stack { flex-direction: column; justify-content: center; align-items: stretch; }
/* the phone face of a field: one "Label: value" line, or a block of them */
.list-line  { padding: 0 var(--s4) var(--s1); font-size: var(--t-label); color: var(--c-ink); }
.list-lines { display: flex; flex-direction: column; gap: var(--s1); font-size: var(--t-label); color: var(--c-ink); }
.list-key { font-weight: 600; }
.list-address { line-height: var(--lh-body); color: var(--ink-2); }
/* a searched term, wherever the list or a reason line prints it (search D11): the warning tint, text colour unchanged */
mark { background: var(--c-warning-soft); color: inherit; border-radius: var(--radius); }
/* the row's one reason line (search D12): "Label: value" naming the hidden field the row matched on; `.truncate` + `title=` carry the long value */
.list-reason { font-size: var(--t-caption); color: var(--ink-3); }
/* A row whose primary cell is a narrow número track carries its reason as the row's LAST child, one node at both widths:
   the phone card's bottom line (pulled up to the primary cell's --s2 rhythm, kebab inset kept), and on the desktop grid
   its own line from the second track to before ações (user 2026-10-21: row-wide line). */
:is(.list-row, .list-link) > .list-reason { margin-top: calc(-1 * var(--s2)); padding: 0 calc(var(--s7) + var(--s2)) var(--s4) var(--s4); }
/* header strip (desktop only: `desk-only`); each label ellipsizes in its track and pads like a body cell (`.list-cell`, --s4
   each side) — a view no longer adds `px-4` per header span. `is-end` right-aligns a numeric / action label. */
.list-head > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-inline: var(--s4); }
.list-head > .is-end { text-align: right; }
/* The actions header sits over the rows' `.list-actions` (right-aligned, --s3 in from the edge): same inset, same side.
   Keyed on the rows so a list whose last column is data keeps its left-aligned label; the rowActions variant below keeps --s1. */
@media (min-width: 1024px) {
  #list-content:has(.list-actions) .list-head > :last-child { text-align: right; padding-inline: var(--s3); }
}
.list-head.is-spaced { margin-top: var(--s4); }
.list-sort { position: relative; display: inline-flex; align-items: center; min-height: var(--ctl-s); padding: 0 var(--s4);
  text-align: left; cursor: pointer; border: 0; border-radius: var(--radius); background: transparent; color: inherit; }
.list-sort:focus-visible { outline: none; box-shadow: var(--focus); }
.list-sort > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-sort.is-sorted { color: var(--c-ink); }
/* the chevron rides INLINE after the label (user 2026-10-14): absolutely positioned at the track's right edge it sat
   570 px from "Cliente" in a 1fr track at 1920, and a chevron that far from its column header reads as a stray glyph.
   The button still fills the track, so the whole header cell stays the sort target; a label too long for its track
   ellipsizes in the span (`min-width: 0` above) instead of pushing the chevron out. */
.list-sort-icon { flex-shrink: 0; width: 12px; height: 12px; margin-left: var(--s1); color: var(--ink-3); }
.list-sort.is-sorted .list-sort-icon { color: currentColor; }
.list-sort-icon.is-up { transform: rotate(180deg); }
.list-icon { width: 16px; height: 16px; flex-shrink: 0; }
.list-icon.is-xs { width: 12px; height: 12px; }
.list-reset { gap: var(--s1); }
/* #list-more: the scroll sentinel, a quiet full-width text button */
.list-more { display: flex; width: 100%; align-items: center; justify-content: center; gap: var(--s2); margin: var(--s2) 0;
  height: var(--ctl-l); padding: 0 var(--s3); border: 0; border-radius: var(--radius); background: transparent;
  font-size: var(--t-label); font-weight: 600; color: inherit; cursor: pointer; }
.list-more:hover { background: var(--g-100); }
/* search bar, filter strip, numero summary */
.list-search-bar { margin-bottom: var(--s4); }
/* F9: the `;` help line sits in flow under the box (app.css .list-search-help), so the row aligns at the top — centred, the
   box would ride half a line above the buttons beside it (box and buttons share --ctl, so top-aligned IS aligned) */
.list-search-bar .cluster { align-items: flex-start; }
.list-search { position: relative; min-width: 0; flex: 1 1 10rem; }
/* The chip field (user, 2026-10-19: the boxes and x are back): an .input that wraps its chips and the typed text and grows
   with them. The field carries the border and the focus ring (.input:focus-within); the inner text box is bare. */
.input.list-search-field {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1);
    width: 100%; height: auto; min-height: var(--ctl-l); padding: var(--s1) var(--s3); cursor: text;
}
.list-search-field .list-search-box {
    flex: 1 1 6rem; min-width: 6rem; height: auto; padding: 0; border: 0; outline: 0; background: transparent;
    font-size: var(--t-body);
}
/* a chip: the term and its x — the x is a 24px target (WCAG 2.5.8) inside a chip that grows to fit it */
.list-search-chip { height: auto; min-height: var(--s5); gap: var(--s1); padding-inline-end: 0; }
.list-search-chip > button {
    display: inline-flex; align-items: center; justify-content: center; min-width: var(--s5); min-height: var(--s5);
    cursor: pointer; line-height: 1;
}
/* an active-filter chip in #filter-form (activeFilterChip): two targets side by side — the value (a link to the entity)
   and the x that clears the filter; a long cliente name wraps. One control tall on the phone like the pill labels
   beside it (app.css), the x a square of the same size (WCAG 2.5.8). */
.list-filter-chip { height: auto; min-height: var(--s5); gap: 0; padding-inline-end: 0; max-width: 100%; white-space: normal; text-align: start; }
.list-filter-chip > a { display: inline-flex; align-items: center; min-height: var(--s5); }
.list-filter-chip > a:first-child:hover { text-decoration: underline; }
.list-filter-chip > .list-filter-chip-x { justify-content: center; min-width: var(--s5); padding-inline: var(--s2); margin-inline-start: var(--s1); }
@media (max-width: 1023.98px) {
    .list-filter-chip > a { min-height: var(--ctl-l); }
    .list-filter-chip > .list-filter-chip-x { min-width: var(--ctl-l); }
}
.actions > .list-search-go { flex: none; }
/* G-5: the clear ✕ sits over the field's right end (as the password eye does); while it is there the field keeps a
   control's width free under it. One control tall at each tier: --ctl-l under the phone's field, --ctl-s from 1024. */
.list-search-clear { position: absolute; top: 0; right: 0; }
.list-search:has(> .list-search-clear) > .list-search-field { padding-inline-end: var(--ctl-l); }
.list-filters { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-bottom: var(--s4); }
.list-dates { flex-basis: 100%; }
.numero-list-summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-bottom: var(--s4); font-size: var(--t-label); }
/* filter pills: solid = selected, outline = not; the selected status pill wears its tone (data-tone) */
.filter-pill-row { display: flex; width: 100%; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.filter-pill { gap: var(--s1); cursor: pointer; transition: background-color .15s, border-color .15s, color .15s; }
.filter-pill:not(.is-selected):hover { background: var(--g-100); }
.filter-pill[data-tone="success"] { border-color: var(--c-success); background: var(--c-success-soft); color: var(--c-success); }
.filter-pill[data-tone="warning"] { border-color: var(--c-warning); background: var(--c-warning-soft); color: var(--c-warning); }
.filter-pill[data-tone="error"]   { border-color: var(--c-error);   background: var(--c-error-soft);   color: var(--c-error); }
/* empty states */
.list-empty { padding-block: var(--s6); text-align: center; }
.list-empty.is-note { font-style: italic; }
.list-empty > * + * { margin-top: var(--s2); }
.list-empty a { font-size: var(--t-label); }
.empty-prompt { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s4);
  padding-block: calc(var(--s7) + var(--s4)); }
.empty-prompt > svg { width: 64px; height: 64px; }
.empty-prompt > div { text-align: center; }
.empty-prompt p + p { margin-top: var(--s2); font-style: italic; }
/* combobox options (server: Lists.kt comboboxOptions; client: combobox.ts) */
.combobox-no-results { padding: var(--s3) var(--s4); font-size: var(--t-label); font-style: italic; }
.combobox-option { padding: var(--s2) var(--s4); cursor: pointer; }
.combobox-option:hover, .combobox-option:focus { background: var(--g-100); }
.combobox-option > div { display: flex; flex-direction: column; }
.combobox-option > div > :first-child { font-weight: 600; }
.combobox-option > div > :nth-child(2) { font-size: var(--t-caption); color: var(--ink-3); }
/* report units */
.list-group-head { margin-bottom: var(--s2); }
.totals-label { min-width: 0; font-weight: 700; }
.totals-value { flex-shrink: 0; text-align: right; font-weight: 700; color: var(--c-primary); }
.list-period { max-width: 20rem; }
a.stat-tile:hover { border-color: color-mix(in srgb, var(--c-primary) 60%, transparent); }
.kpi-strip { display: grid; gap: var(--s3); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1024px) {
  .list-rows { display: block; gap: 0; border: 1px solid var(--c-line); border-top: 0; }
  .list-rows > * + :not(.list-more) { border-top: 1px solid var(--c-line); }   /* not above the #list-more sentinel */
  .list-row { display: grid; align-items: stretch; border: 0; border-radius: 0; }
  article.list-row:nth-of-type(even) { background: var(--g-50); }
  article.list-row:hover { background: color-mix(in srgb, var(--c-primary) 8%, var(--c-bg)); }
  /* (0,2,0): a view's plain padding utility on the primary cell (`pb-3`, phone spacing) must not reach the table row */
  .list-row .list-primary { flex-direction: row; align-items: center; padding: var(--s2) var(--s4); }
  :is(.list-row, .list-link) > .list-reason { grid-row: 2; grid-column: 2 / -2; margin-top: calc(-1 * var(--s1)); padding: 0 var(--s4) var(--s2); }
  .list-title { font-size: var(--t-label); font-weight: 400; line-height: var(--lh-body); }
  .list-cell { display: flex; padding: var(--s2) var(--s4); }
  .list-actions { position: static; align-items: center; padding: 0 var(--s3); }
  /* A rowActions list's AÇÕES track is the token (`--list-actions-w` = the pair + this inset; the `*-list-cols` lines below
     read it): the cell and the header label over it take the same --s1 inset, so the label (pt AÇÕES, en ACTIONS) fits
     the track and ends flush with the trash. The header strip and each row are separate grids wearing one cols class,
     so the track is a token, not `max-content`: content-sized tracks would resolve from different content (label vs
     icons) and kink the column rule between header and rows. (user 2026-10-14: no empty space in AÇÕES) */
  .list-actions:has(> .row-actions) { padding-inline: var(--s1); }
  #list-content:has(.row-actions) .list-head > :last-child { padding-inline: var(--s1); }
  /* the lab table's vertical rules: every column after the first, header and rows alike */
  .list-head > * + *, .list-row .list-cell, .list-row .list-actions { border-left: 1px solid var(--c-line); }
  .list-head { display: grid; align-items: stretch; background: var(--c-bg-2); border: 1px solid var(--c-line); }
  .list-head > * { line-height: calc(var(--ctl-s) + var(--s1)); }   /* the lab th: 36px */
  .list-more { height: var(--ctl-s); }
  .list-search { min-width: 12rem; }
  .input.list-search-field { min-height: var(--ctl-s); padding-block: 2px; }
  .list-search-field .list-search-box { font-size: var(--t-label); }
  .list-search:has(> .list-search-clear) > .list-search-field { padding-inline-end: var(--ctl-s); }
  .list-dates { flex-basis: auto; }
  .kpi-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* the endereco tracks (Lists.kt enderecoListRow + EnderecoListView's header) */
  /* RUA is the text column (user 2026-10-15): it keeps the elastic 1.5fr so a street + number stays on one
     line at office widths instead of growing the row to two; NOME holds 1fr, BAIRRO/CIDADE split the rest. */
  .endereco-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1.5fr) minmax(0,0.75fr) minmax(0,0.75fr) minmax(0,var(--list-actions-w)); }
  /* Every column from 1024 (user, 2026-10-13: information never depends on the width). At 1024 ~720-760px sit beside the
     sidebar: fixed tracks are trimmed to their content, the text columns share the rest and truncate (title attr). */
  /* orcamento: numero, localizacao, data, valor, status, cliente, acoes (OrcamentoListView) */
  /* F6 (ui-feedback 2026-10-13): Cliente is the only fr track — localizacao is one or two words, valor fits
     "Produtividade/dia: R$ 12.729,00" on one line once wide. The % caps keep 1024 close to before (fixed 10rem/11rem
     tracks left Cliente 24px of a ~760px row, 145px before, ~130px with the caps; Chromium grid track sizes).
     Número (user 2026-10-14): 8rem/14% holds a nine-digit número on one line (96px of text at 14px + the cell's two
     --s4 insets) — at 6rem it broke mid-number while Cliente sat half empty. */
  .orcamento-list-cols { grid-template-columns: minmax(0,min(8rem,14%)) minmax(0,min(10rem,12%)) minmax(0,7rem) minmax(0,min(11rem,18%)) minmax(0,7rem) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  /* servico: orcamento, data (+ time · tipo), cliente (+ responsavel), endereco, status, acoes (ServicoListView) */
  .servico-list-cols { grid-template-columns: minmax(0,7rem) minmax(0,9rem) minmax(0,1fr) minmax(0,1.4fr) minmax(0,8rem) minmax(0,var(--list-actions-w)); }
  /* one class per list, named after its view (the header strip and every row wear it) */
  /* E10: a list's unidade column exists only while the scope spans several unidades; `<x>-unidades-list-cols` carries its
     track, `<x>-list-cols` is the same list without it (user, maquina, carro, equipe). */
  .user-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,6rem) minmax(0,var(--list-actions-w)); }
  .user-unidades-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,6rem) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  .carro-list-cols { grid-template-columns: minmax(0,7rem) minmax(0,8rem) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  .carro-unidades-list-cols { grid-template-columns: minmax(0,7rem) minmax(0,8rem) minmax(0,1fr) minmax(0,12rem) minmax(0,var(--list-actions-w)); }
  .contrato-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,7rem) minmax(0,var(--list-actions-w)); }
  .contrato-dados-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  .email-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,12rem) minmax(0,var(--list-actions-w)); }
  /* equipe AÇÕES = the icon pair's token + the Mapa · Estoque links (~155px at 1024/1920, R2 2026-10-14: the flat 10rem
     spilled Mapa 63px into UNIDADE); reading the token keeps it right when a coarse pointer grows the icons. */
  .equipe-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,6rem) minmax(0,calc(var(--list-actions-w) + 10rem)); }
  .equipe-unidades-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,6rem) minmax(0,12rem) minmax(0,calc(var(--list-actions-w) + 10rem)); }
  /* carga: item, consumo 30d, mínimo = the pedido form's 11rem stepper (`.estoque-qty-area`) + the cell's two --s4 insets */
  .carga-padrao-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,10rem) minmax(0,13rem); }
  /* estoque: item, saldo (+ falta badge), mínimo, movimentação = the +/− pair (2 × --ctl-s + --s4) under its own header word, ações */
  .estoque-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,12rem) minmax(0,6rem) minmax(0,9rem) minmax(0,var(--list-actions-w)); }
  /* pedido: número + its "· Automático" caption (~115px with the cell inset), tipo, destino, status holding "Em separação"
     on one line (Parcial wraps under it on purpose), responsável, itens = the ITENS header word */
  .pedido-list-cols { grid-template-columns: minmax(0,7.5rem) minmax(0,8rem) minmax(0,1fr) minmax(0,11rem) minmax(0,1fr) minmax(0,5rem); }
  .hmdm-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,18rem) minmax(0,6rem); }
  /* A's rule (user 2026-10-14): the slack goes to the TEXT column, never to a short one. Número is bounded at 8rem —
     1fr on it gave a 5-digit code 543 px per column at 1600 and ~1190 px on the replica at 1920. Unidade atual is the
     text column at every scope (máquinas move between unidades, the one list exempt from E10; user 2026-10-19 — the
     single-scope class without it left Número and Data floating beside an empty strip), Ações keeps the token track. */
  .maquina-list-cols { grid-template-columns: minmax(0,8rem) minmax(0,1fr) minmax(0,12rem) minmax(0,var(--list-actions-w)); }
  /* Máquina (the name) is the text column here; tipo/dias/data are bounded. */
  .maquina-calendar-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,12rem) minmax(0,9rem) minmax(0,10rem) minmax(0,var(--list-actions-w)); }
  .orcamento-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,8rem) minmax(0,13rem) minmax(0,9rem) minmax(0,var(--list-actions-w)); }
  .ponto-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,18rem) minmax(0,var(--list-actions-w)); }
  .unidade-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  /* Conta bancária: apelido · the account lines (the long text) · unidade · actions. */
  .conta-bancaria-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,2fr) minmax(0,1fr) minmax(0,var(--list-actions-w)); }
  .kit-config-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,5rem); }
}
/* ===== DS-E E8a · kit forms, detail, dialog, actions — the kit's own utilities as component CSS (rule a) ===== */
/* ── kit · icon (Actions.kt icon, the kit's heroIcon calls): SPEC §1.8 renders icons at 16 (S) and 20 (M) ── */
.icon-s { width: 16px; height: 16px; }
.icon-m { width: 20px; height: 20px; }
/* ── kit · check boxes: every DaisyUI .checkbox/.radio reads the one size token by width tier, as .check does
 * (tokens.css --check: 24 below 1024, 20 from it). (0,2,1) out-ranks the compat 1.5rem box and its -sm/-xs steps,
 * so no modifier drops a box under the WCAG 2.2 target on the phone. */
input[type="checkbox"].checkbox, input[type="radio"].radio { width: var(--check); height: var(--check); }
/* ── kit · field (Forms.kt fieldWrapper, configUnidadeField, telefone; DatePicker.kt dateField) ──
 * The wrapper takes its column's width (it was `form-control w-full`; a module's own copy becomes `form-control form-field`).
 * Its controls need no width: `.form-control` is a flex column, so they stretch. */
.form-field { width: 100%; }
.form-field .search > .input { width: 100%; }
.form-field-value { padding: var(--s2); background: var(--g-100); }
/* a label that wraps a radio / checkbox: the whole row is the target */
.label-pick { cursor: pointer; }   /* app-components.css keys the 48px touch row, the label-text ink and the control shrink on it */
/* telefoneInputDual: its two controls lay out as grid children of the form */
.telefone-dual { display: contents; }
/* a derived or locked input (readonly currency, prazo, the visit's cliente and endereço): grey ground; orcamento.ts toggles `is-readonly` with the manual box.
   `is-fill`: an input whose parent is not a flex column (a plain div, a table cell) takes its parent's width */
.input.is-readonly { background-color: var(--c-bg-2); }
.input.is-fill { width: 100%; }
/* currencyInputPair: fills its cell */
.input-money { width: 100%; }
.telefone-error { display: flex; align-items: center; gap: var(--s1); }
/* M25's connected group option (Forms.kt radioOption): the radio covers its label unseen (a tap and Playwright's check()
 * land on it, and it keeps focus); the chosen one wears the outline-active ink pair; focus rings the label. Disabled comes
 * first so a confirmed checklist still shows its answer. R25: a hovered choice keeps its fill (the unlayered
 * `.btn-outline:not(.btn-active):hover` tint is (0,3,0), so the hover twin is (0,4,0)). */
.segment { position: relative; }
.segment > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; opacity: 0; }
.segment:has(:disabled) { pointer-events: none; cursor: not-allowed; border-color: transparent;
  background-color: color-mix(in srgb, var(--c-neutral) 20%, transparent); color: color-mix(in srgb, var(--g-900) 20%, transparent); }
.segment:has(:checked), .btn-outline.segment:has(:checked):hover { background-color: var(--g-900); border-color: var(--g-900); color: var(--g-0); }
.segment:has(:focus-visible) { outline-style: solid; outline-width: 2px; outline-offset: 2px; }
.step-button { min-width: var(--ctl-l); }
/* The number between a stepper's two step buttons: a 5rem centred field (the kit specimen; the pedido row fills instead, `.estoque-stepper > .input`). */
.input.step-input { width: 5rem; text-align: center; }
/* ── kit · combobox (Forms.kt searchableCombobox; combobox.ts toggles `hidden` on the panel, the × and the required line) ── */
.searchable-combobox { position: relative; }
.combobox-row { display: flex; }
.combobox-box { position: relative; flex: 1; min-width: 0; }
.searchable-combobox .combobox-search { width: 100%; padding-right: calc(var(--s6) + var(--ctl-s)); }
.combobox-clear-slot { position: absolute; right: var(--s6); top: 50%; transform: translateY(-50%); }
/* the phone row rule `:where(.actions) > .btn { flex: 1 1 0 }` would stretch the × */
.combobox-clear-slot > .combobox-clear { flex: none; }
.combobox-chevron { position: absolute; right: var(--s2); top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--ink-3); }
.combobox-dropdown { position: absolute; z-index: var(--z-dialog); width: 100%; margin-top: var(--s1); background: var(--c-bg);
  border: 1px solid var(--c-line); box-shadow: var(--shadow-raise); max-height: calc(var(--visual-viewport-height, 100vh) * 0.45);
  overflow-y: auto; overscroll-behavior: contain; }
@media (min-width: 1024px) { .combobox-dropdown { max-height: 240px; } }
@media (max-width: 1023.98px) {
  /* M30: open, the list flows in the page under its field and the document's own scroll reaches every row (the vinculados
     shape); hanging absolute it opened under the fixed bottom nav. `hidden` still takes it out of flow when closed. */
  .combobox-dropdown { position: static; max-height: none; overflow: visible; }
}
.combobox-note { padding: var(--s3) var(--s4); }
.combobox-loading > .loading { margin-right: var(--s2); }
.combobox-required-error { margin-top: var(--s1); font-size: var(--t-caption); }
/* ── kit · colour swatches (Forms.kt colorSwatches): a round radio face, ringed while chosen ── */
.swatch { cursor: pointer; }
.swatch-dot { display: block; width: var(--ctl-s); height: var(--ctl-s); border-radius: 50%; border: 1px solid var(--c-line); }
.swatch > input:checked + .swatch-dot { box-shadow: 0 0 0 2px var(--c-bg), 0 0 0 4px var(--c-primary); }
/* ── kit · form page (FormPage.kt) ── `.form-flow` is the vertical rhythm the form and a section group had as `space-y-4`
 * (kept as margins, not a flex gap: the first visible child keeps the offset a leading hidden input gives it) */
.form-flow > :not([hidden]) ~ :not([hidden]) { margin-top: var(--s5); margin-bottom: 0; }
.form-column, .form-solo { width: 100%; min-width: 0; }
@media (min-width: 1024px) {
  .form-column, .form-solo { max-width: var(--w-form); }
  .form-solo { margin-inline: auto; }
  /* a single-section form's Cancelar · Salvar box; `.sticky-action-bar` (app-components.css, later) unboxes the bar from lg */
  .sticky-action-bar.form-actions-box { border: 1px solid var(--c-line); padding: var(--s3) var(--s5); margin-top: var(--s4); }
}
/* ── kit · rail layout (FormPage.kt formLayout, Detail.kt detailPage): the sticky section rail beside the column from lg ── */
@media (min-width: 1024px) { .rail-layout { display: flex; align-items: flex-start; gap: var(--s5); } }
/* ── kit · sections (Sections.kt) ── the action row under a section head, the rail's label, the compact disclosure, the count chip */
.section-action { margin-bottom: var(--s3); }
.form-rail-label { margin-bottom: var(--s2); padding-left: var(--s3); }
.detail-comments-collapse { margin-top: var(--s4); background-color: var(--c-bg-2); }
.detail-comments-collapse > summary.collapse-title { min-height: 0; padding-block: var(--s3); font-size: var(--t-label); line-height: 20px; font-weight: 600; }
.detail-comments-collapse > .collapse-content > * + * { margin-top: var(--s3); }
.count-badge { margin-left: var(--s2); }
/* ── kit · destructive ghost button (Actions.kt tertiary / iconButton): the ghost keeps its shape and takes the error ink ── */
.btn-ghost.is-danger { color: var(--c-error); }
/* ── kit · overlay circle (Actions.kt OVERLAY_CIRCLE): the × / ✎ on a thumbnail; ButtonPlacement (G4) knows one by this class ── */
.overlay-circle { position: absolute; }
/* ── kit · detail (Detail.kt) ── */
.detail-column { width: 100%; min-width: 0; }
@media (min-width: 1024px) { .detail-column { max-width: var(--w-detail); } }
@media (max-width: 1023.98px) {
  /* D3 (mobile-consistency): one detail-label face on the phone — a `fieldLabel()` inside a detail card reads like
     `dataField`'s .field-label-lg (14/600), so the orçamento (fieldLabel ×21) and agendamento (dataField) pages no longer
     differ. Scoped to the detail page's column, not .form-section-card, which the form pages share. Desktop unchanged. */
  .detail-column .field-label { font-size: var(--t-label); font-weight: 600; line-height: 1.375; }
}
.rail-back { margin-top: var(--s5); }
.collapse-card { border: 1px solid var(--c-line); background: var(--c-bg); box-shadow: var(--shadow-rest); }
.collapse-card > .collapse-title { font-size: var(--t-body); }
.inline-empty { padding-block: var(--s4); text-align: center; }
.inline-empty-icon { display: block; width: 32px; height: 32px; margin: 0 auto var(--s2); color: var(--ink-3); }
.inline-empty-title { font-size: var(--t-label); font-weight: 600; }
.inline-empty-hint { margin-top: var(--s1); font-size: var(--t-caption); }
.data-field { min-width: 0; }
.data-field-value { font-weight: 600; line-height: var(--lh-body); overflow-wrap: break-word; }
.data-field-value.is-money { font-size: var(--t-title); }
.field-value { font-weight: 600; }
/* The phone face of `telLink`: the number text as a thumb-sized tel: target below 1024 (the desk face is a plain .data-field-value). */
.tel-number { display: inline-flex; align-items: center; min-height: var(--ctl-l); font-weight: 600; }
.spec-groups { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; gap: var(--s3); }
.spec-group { min-width: 0; }
.spec-group > h3 { margin-bottom: var(--s2); color: var(--c-primary); }
@media (min-width: 1024px) {
  .spec-groups { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spec-group.is-lead { grid-column: span 2 / span 2; }
}
/* linkedRow: a whole-row link, title + meta, then status, flags and "Ver →"; one line from lg */
.linked-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2); padding: var(--s2);
  margin-inline: calc(-1 * var(--s2)); border-bottom: 1px solid var(--g-100); cursor: pointer; color: inherit; text-decoration: none;
  transition: background-color 150ms ease; }
.linked-row:last-child { border-bottom: 0; }
.linked-row:hover { background: var(--g-100); }
.linked-row-main { flex: 1; min-width: 0; }
.linked-row-title { font-weight: 600; }
.linked-row-end { flex-shrink: 0; }
@media (min-width: 1024px) { .linked-row { flex-wrap: nowrap; } }
@media (max-width: 1023.98px) { .linked-row { min-height: var(--ctl-l); } }
/* the row's `value` slot: the record's figure right of its status, tabular so a column of rows lines up */
.linked-row-value { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* phone: a row carrying a value (`is-rich`) gives its end cluster a line of its own — in one line `.linked-row-main`
   (flex: 1) shrank to nothing under the badges + value and the título painted beneath them; "Ver →" keeps the right edge */
@media (max-width: 1023.98px) {
  .linked-row.is-rich .linked-row-main { flex: 1 1 100%; }
  .linked-row.is-rich .linked-row-end { flex: 0 0 100%; }
  .linked-row.is-rich .linked-row-end > .t-label:last-child { margin-left: auto; }
}
/* linked card (AgendamentoDetailView orcamentoResumoCard): the one linked record that earns a summary, as a whole-card link —
   número + status, then its fields wrapping side by side, then flags and "Ver →" */
.linked-card { display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4); border: 1px solid var(--c-line);
  border-radius: var(--radius); background: var(--c-bg); box-shadow: var(--shadow-rest); color: inherit; text-decoration: none;
  transition: background-color 150ms ease; }
.linked-card:hover { background: var(--g-50); }
.linked-card-fields { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s6); }
/* addressBlock: the lines, the maps CTA and the open action; labelled = the summary card's footer row */
.address-block.is-labelled { display: grid; gap: var(--s2); margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--c-line); }
.address-block-body { min-width: 0; }
.address-body { display: flex; flex-direction: column; gap: var(--s2); font-size: var(--t-label); color: var(--ink-2); }
.address-lines { display: flex; flex-direction: column; gap: var(--s1); }
.address-condo, .address-street { font-weight: 600; color: var(--c-ink); }
.address-condo { font-size: var(--t-body); }
.address-none { color: var(--ink-3); font-style: italic; }
@media (min-width: 1024px) {
  /* baseline, not center: the caps label, the street and the buttons' text share one line (centring left the
     smaller label riding a few px high, user 2026-10-21) */
  .address-block.is-labelled { grid-template-columns: auto minmax(0, 1fr) auto; align-items: baseline; gap: var(--s4); }
  .address-body { flex-direction: row; align-items: baseline; gap: var(--s4); }
  .address-lines { flex: 1; min-width: 0; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s5); }
}
/* clienteMessageCard: one block per stage, ruled apart */
.cliente-message + .cliente-message { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--c-line); }
.cliente-message > :is(pre, p, ul) { margin-top: var(--s1); }
.cliente-message > pre { padding: var(--s2); background: var(--g-100); font-size: var(--t-label); white-space: pre-wrap; overflow-wrap: break-word; }
.cliente-message > ul { padding-left: 0; list-style: disc inside; font-size: var(--t-label); }
.cliente-message-actions { margin-top: var(--s2); }
.cliente-message.is-unavailable > h3 { color: var(--ink-3); }
/* ── kit · actions (Actions.kt): a blocked menu entry (a Request, or a Link pointing at its hint) stacks its reason under the label ── */
/* Only a row that carries a reason stacks: a bare disabled row (the annotator's Mais sheet) keeps the row shape. */
.menu-panel .menu-disabled :is(a, button):has(.menu-reason) { flex-direction: column; align-items: flex-start; gap: var(--s1); height: auto; padding-block: var(--s2); }
.menu-reason { font-size: var(--t-caption); opacity: .7; white-space: normal; text-align: left; }
.menu-panel .is-inert { pointer-events: none; }
/* ── kit · page header (Chrome.kt pageHeaderBlock / headerControls / pageTitle) ──
 * Phone base: one column, the h1 screen-reader-only (the top bar shows it, M1). From 1024: title and controls share a
 * wrapping row, controls pushed right. `is-top` top-aligns a header with a subtitle; `is-phone-flush` drops the margin
 * on the phone when nothing in the block renders there (the 24px gap under the top bar, user 2026-10-08). */
.page-header { display: flex; flex-direction: column; gap: var(--s3); margin-bottom: var(--s5); }
.page-header-main { flex: 1 1 auto; min-width: 0; text-align: left; }
.actions.header-controls { flex-wrap: wrap; width: 100%; }
/* Below lg a header that keeps its secondaries as buttons (PageHeader.secondaryOnPhone: contrato's two PDFs beside "Enviar
   para assinatura", 2026-10-20) wraps by label instead of splitting one row into 80px columns with a three-line primary:
   the basis is the label's width, so the row breaks between controls, and each grows into what is left (the inherited
   min-width: 0 still lets one label longer than the row wrap inside it). Outranks app-components'
   `:where(.actions) > .btn/form { flex: 1 1 0 }`; from lg the header row is `width: auto` and unaffected. */
@media (max-width: 1023.98px) {
  .actions.header-controls > :is(.btn, form) { flex: 1 1 auto; }
}
/* The phone's header kebab (secondaries folded into one sheet, M10) sits at the row's right edge, under the top bar's
   own ⋮ side: a page whose header renders nothing else below lg (the estoque list) had it alone at the left, reading
   as an empty box (user 2026-10-20). A HEADER-face primary beside it still takes the row (`:where(.actions) > .btn`). */
.actions.header-controls > .menu { margin-left: auto; }
.header-slot { display: contents; }
.btn.fab { gap: var(--s2); padding-inline: var(--s4); border-radius: 9999px; box-shadow: var(--shadow-float); }
.page-header.is-phone-flush { margin-bottom: 0; }
@media (min-width: 1024px) {
  .page-header.is-phone-flush { margin-bottom: var(--s5); }
  .page-header { flex-direction: row; flex-wrap: wrap; justify-content: space-between; align-items: center; }
  .page-header.is-top { align-items: flex-start; }
  .actions.header-controls { width: auto; margin-left: auto; justify-content: flex-end; }
}

/* ── kit · status / flag badges (Chrome.kt toneBadgeClasses, flagWarning) ── one soft shape per tone (M24) */
.badge-status.is-success { border-color: transparent; background-color: var(--c-success-soft); color: var(--c-success); }
.badge-status.is-warning { border-color: transparent; background-color: var(--c-warning-soft); color: var(--c-warning); }
.badge-status.is-error   { border-color: transparent; background-color: var(--c-error-soft); color: var(--c-error); }
.badge-status.is-neutral { border-color: transparent; background-color: var(--g-100); color: var(--c-ink); }
.flag-warning, .flag-success, .flag-neutral, .flag-info { display: inline-flex; align-items: flex-start; gap: var(--s1); font-size: var(--t-caption); font-weight: 600;
  line-height: var(--lh-tight); color: var(--c-warning); }
.flag-warning-dot, .flag-success-dot, .flag-neutral-dot, .flag-info-dot { flex-shrink: 0; width: 6px; height: 6px; margin-top: var(--s1); border-radius: 50%; background: var(--c-warning); }
.flag-success { color: var(--c-success); }
.flag-success-dot { background: var(--c-success); }
.flag-neutral { color: var(--ink-2); }
.flag-neutral-dot { background: var(--ink-3); }
.flag-info { color: var(--c-info-text); }
.flag-info-dot { background: var(--c-info); }

/* ── kit · back nav (Chrome.kt backNav) ── the arrow button keeps its content width in a phone actions row */
.back-nav { margin-bottom: var(--s4); }
.back-nav > .btn { flex: none; }
.back-nav-icon { width: 16px; height: 16px; margin-right: var(--s2); }

/* ── kit · page alerts (Chrome.kt validationSummary, writeContextBanner) ── */
.page-alert { margin-bottom: var(--s4); }
.alert-icon { flex-shrink: 0; width: 24px; height: 24px; }
.validation-list { list-style: disc inside; font-size: var(--t-label); }
.write-context-note { font-size: var(--t-caption); line-height: calc(var(--t-caption) * 4 / 3); }

/* ── kit · creator strip (Chrome.kt creatorStrip / creatorStripSplit) ── the 4px edge marker; creatorSwatch paints
 * it from data-swatch-color, the grey only shows for a user without a colour. The row is the positioned parent. */
.creator-strip { position: absolute; left: 0; top: 0; bottom: 0; width: var(--s1); border-radius: var(--radius) 0 0 var(--radius);
  background: var(--g-200); }
.creator-strip.is-top { bottom: auto; height: 50%; border-radius: var(--radius) 0 0 0; }
.creator-strip.is-bottom { top: auto; height: 50%; border-radius: 0 0 0 var(--radius); }

/* ── kit · maps CTA (Chrome.kt mapsCta) ── */
.maps-cta-icon { flex-shrink: 0; width: 16px; height: 16px; }
/* ── kit · agenda (Agenda.kt) ── the toolbar shell, the dated lists' day header and create link and the legend block.
   Phone is the base; the row layout, the sticky offset and the desktop control sizes start at 1024. */
/* agendaShell: sticky under the pinned phone top bar (its live-strip offset), at the top on desktop */
.agenda-shell { position: sticky; top: var(--mobile-topbar-live-strip); z-index: var(--z-sticky); background: var(--c-bg-2);
  padding: var(--s2) 0; margin-bottom: var(--s2); }
.agenda-bar { display: flex; flex-direction: column; gap: var(--s2); }
.agenda-group { display: flex; }
.agenda-list-views { margin-bottom: var(--s3); }
.segments.agenda-segments { width: 100%; }
/* ‹ › Hoje: square at the control height (48 phone, 40 desktop); the range label takes the rest of the nav row */
.btn.agenda-nav { flex: none; min-width: var(--ctl-l); }
.agenda-range { flex: 1 1 0%; text-align: center; font-weight: 600; }
/* the view segments share the phone row in equal tracks */
.btn.agenda-seg { flex: 1 1 0%; min-width: 0; padding-inline: var(--s2); }
/* agendaDayHeader: the date row between a dated list's rows; today in the primary ink */
.agenda-day-head { display: flex; align-items: baseline; gap: var(--s3); padding: var(--s3) 0 var(--s1); font-size: var(--t-label); }
.agenda-day-head > .num { font-weight: 600; }
.agenda-day-head > .num.is-today { color: var(--c-primary); font-weight: 700; }
/* dayCreateLink: tertiary text, 48 px tall on the phone (M4 touch floor), underlined on hover */
.link.agenda-create { display: inline-flex; align-items: center; min-height: var(--ctl-l); text-decoration-line: none; }
.link.agenda-create:hover { text-decoration-line: underline; }
/* agendaLegends */
.agenda-legends { margin-top: var(--s5); }
/* the marker legend's ring = the warning outline the month chip's glyph and the ServicoBoardView card wear */
.legend-swatch--ring { border-color: var(--c-warning); }
@media (min-width: 1024px) {
  .agenda-shell { top: 0; }
  .agenda-bar { flex-direction: row; align-items: center; }
  .segments.agenda-segments { width: auto; }
  .btn.agenda-nav { min-width: var(--ctl-m); }
  .agenda-range { flex: none; padding-inline: var(--s2); }
  .btn.agenda-seg { flex: none; padding-inline: var(--s3); }
  .agenda-day-head { padding: var(--s2) var(--s4); background: var(--g-50); }
  .link.agenda-create { min-height: 0; }
}
/* ── kit · file input (Media.kt fileInputField) ── */
.file-field { width: 100%; }

/* ── kit · gallery (Media.kt imageGallery) — pick tiles, the desktop row break, the upload preview, the count line ──
 * The tiles share their own full-width row in equal widths, the thumbnails wrap below: two controls tall on the phone
 * (size-l row: 2 × --ctl-l), one line from 1024. `.btn.gallery-pick` is (0,2,0): app-components.css `:where(.actions) .btn` sizes every row button at (0,1,0)
 * and comes later in the bundle. */
.gallery-field { width: 100%; }
.gallery-strip { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s2); }
.actions.gallery-picks { flex-basis: 100%; }
/* G-4: a square at the default text size, a taller/wider tile under large Android text — min sizes, never a fixed box
   around a word; the label wraps instead of spilling. */
.btn.gallery-pick { flex: 1 1 0%; flex-direction: column; flex-wrap: nowrap; gap: var(--s1); padding: var(--s1);
  width: auto; min-width: calc(2 * var(--ctl)); max-width: 100%; height: auto; min-height: calc(2 * var(--ctl)); }
.gallery-pick-label { font-size: var(--t-caption); line-height: var(--lh-tight); white-space: normal; overflow-wrap: anywhere; }
.gallery-preview { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s2); }
.gallery-preview:empty { display: none; }
.label-text-alt.gallery-limit { color: var(--c-warning); }
.label-text-alt.gallery-count { color: var(--c-info); }
@media (min-width: 1024px) {
  .btn.gallery-pick { flex-direction: row; width: auto; min-width: 0; height: auto; min-height: var(--ctl); padding: var(--s1) var(--s4); }
  .gallery-pick-label { font-size: var(--t-label); }
}

/* ── kit · media thumbnails (Media.kt mediaThumbnails, mediaCaption) ──
 * The thumb is the stored 320 px rendition at 160 CSS px, the same size the img/video width/height attributes declare.
 * The ×/✎ buttons hang off the frame's corners; the caption (read-only or editable) sits under the photo. */
.media-thumbs { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s2); }
.media-thumb { display: inline-block; min-width: 0; }
.media-thumb-frame { position: relative; }
.media-thumb-img { width: 160px; height: 160px; object-fit: cover; border: 1px solid var(--c-line); }
a:hover > .media-thumb-img { opacity: .75; }
.btn.media-thumb-del, .btn.media-thumb-ann { right: calc(-1 * var(--s2)); }
.btn.media-thumb-del { top: calc(-1 * var(--s2)); }
.btn.media-thumb-ann { bottom: calc(-1 * var(--s2)); box-shadow: var(--shadow-raise); font-size: var(--t-caption); line-height: 1; }
.media-thumb-map { margin-top: var(--s1); }
.media-thumb .media-thumb-caption { width: 8rem; margin-top: var(--s1); }
.media-caption { margin-top: var(--s1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--t-caption); line-height: var(--lh-tight); color: var(--ink-2); }

/* ── kit · documento editor (Media.kt documentoEditor) — the framed fieldset, the desktop column header and the rows.
 * Phone: each row stacks its labelled fields, a hairline between rows. From 1024 header and rows share one grid; the
 * Estado column (and the remove cell's pinned track) opens on `data-documento-subdivisao-col`, which the server renders
 * and declarativeHandlers.ts updateDocumentoColumns keeps in sync. ── */
.documento-editor { grid-column: 1 / -1; padding: var(--s4); border: 1px solid var(--c-line); border-radius: var(--radius); }
.label-text.documento-legend { padding: 0 var(--s1); }
.label-text-alt.documento-hint { color: var(--ink-3); margin-bottom: var(--s3); }
/* sibling margins, not a flex gap: a phone row's own bottom margin collapses into this one, as before */
.documento-rows > * + * { margin-top: var(--s2); }
.documento-add { margin-top: var(--s2); }
.documento-head { display: none; }
.documento-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); align-items: end;
  border-bottom: 1px solid var(--c-line); padding-bottom: var(--s3); margin-bottom: var(--s3); }
.actions.documento-remove { width: 100%; }
@media (min-width: 1024px) {
  .documento-head { display: grid; gap: var(--s2); font-weight: 600; }
  .documento-head, .documento-row { grid-template-columns: 12rem 1fr auto; }
  [data-documento-subdivisao-col] :is(.documento-head, .documento-row) { grid-template-columns: 12rem 1fr 12rem auto; }
  .documento-row { border-bottom: 0; padding-bottom: 0; margin-bottom: 0; }
  .actions.documento-remove { width: auto; grid-column-start: 3; }
  [data-documento-subdivisao-col] .actions.documento-remove { grid-column-start: 4; }
}
/* ── kit · checklist (Checklist.kt) ── the conference screen: groups (DaisyUI collapse), rows, answer squares, footer, review.
   Selectors that must beat the compat collapse/btn rules or app-components.css's later `.actions`/`.form-section-card .input` carry a
   second class; the rest weigh one. */
.checklist { padding-bottom: calc(2 * var(--s7)); }   /* clears the sticky action bar */
.checklist-group-title { flex-grow: 1; }   /* a group is a kit `.fold`; the title pushes the badge to the end */
.checklist-bulk { padding: var(--s2) var(--s3); }
/* Three row colours for three states (user, 2026-10-08: visible feedback on what is done and what is left): plain = still to
   confirm, soft green = confirmed as expected, soft red = a divergence. Read off data-state, the e2e contract the row carries. */
.checklist-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  border-top: 1px solid var(--c-bg-2); }
.checklist-row[data-state="OK"] { background: color-mix(in srgb, var(--c-success) 10%, transparent); }
.checklist-row[data-state="NOT_OK"] { background: color-mix(in srgb, var(--c-error) 10%, transparent); }
.checklist-row > [data-checklist-panel] { grid-column: 1 / -1; }
.checklist-text { min-width: 0; }
.checklist-name { font-weight: 600; }
.checklist-row[data-state="OK"] .checklist-name { color: var(--ink-3); }
.checklist-mono { font-family: var(--font-mono); }
.checklist-tag { font-family: var(--font-mono); padding: 0 var(--s2); color: var(--c-warning);
  background: color-mix(in srgb, var(--c-warning) 10%, transparent); border-left: 2px solid var(--c-warning); }
.checklist-state { font-size: var(--t-label); font-weight: 600; }
/* M5: the ✓/✗ pair sits 16 px apart; the squares never stretch on the phone's filling action row */
.actions.checklist-pair { gap: var(--s4); }
.btn.checklist-answer { flex: none; }
.checklist-icon { width: 24px; height: 24px; }
/* pressed = the soft fill a done/problem status badge wears, hover included */
.btn.checklist-pressed-ok, .btn.checklist-pressed-ok:hover { border-color: var(--c-success); background-color: var(--c-success-soft); color: var(--c-success); }
.btn.checklist-pressed-error, .btn.checklist-pressed-error:hover { border-color: var(--c-error); background-color: var(--c-error-soft); color: var(--c-error); }
.checklist-qtd { justify-self: end; }
.checklist-row .input.checklist-qtd-input { width: calc(2 * var(--ctl-l)); height: var(--ctl-l); min-height: var(--ctl-l);
  padding: 0 var(--s1); text-align: center; font-weight: 600; }
.checklist-progress { font-size: var(--t-label); }
.checklist-faltas { font-size: var(--t-label); font-weight: 600; color: var(--c-error); }
.checklist-footer-actions { margin-top: var(--s2); }
.checklist-review-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.checklist-review-list { margin-top: var(--s4); background: var(--c-bg); border: 1px solid var(--c-line); }
.checklist-review-list > li { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); padding: var(--s2) var(--s3); }
.checklist-review-list > li + li { border-top: 1px solid var(--c-bg-2); }
.checklist-review-list > li > :first-child { min-width: 0; font-weight: 600; }
.checklist-review-warning { margin-top: var(--s4); }
/* ── kit · fold (CategoriaFolds.kt categoria folds, Checklist.kt groups): one bordered DaisyUI collapse; the categoria band
   (CategoriaFolds.kt) opens a paginated run instead ── */
.fold { background: var(--c-bg); border: 1px solid var(--c-line); margin-top: var(--s2); }
.fold.is-warning { border-color: var(--c-warning); border-left-width: 4px; }
.fold > .collapse-title { display: flex; align-items: center; gap: var(--s2); font-weight: 700; }
/* the rows' own borders and the fold's close the list, so the body has no padding, open state included */
.fold > .collapse-content { padding: 0; }
.categoria-band { width: 100%; min-height: var(--ctl-l); display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4);
  background: var(--g-50); font-size: var(--t-label); font-weight: 600; color: var(--ink-3); }
.categoria-band:hover { background: var(--g-100); }
.categoria-band-name { flex-grow: 1; text-align: left; }
.categoria-band-icon { width: 16px; height: 16px; transition: transform .15s; }
.categoria-band[aria-expanded="true"] .categoria-band-icon { transform: rotate(180deg); }

/* ── kit · consumo rows (ConsumoRows.kt) — item + balance on the left, the one quantity field on the right. The input rule is
   (0,3,0): the rows sit inside `.form-section-card`, whose later (0,2,0) desktop `.input` height would otherwise win. ── */
.consumo-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0; }
.consumo-row-main { flex: 1 1 0%; min-width: 0; }
.consumo-row-name { font-weight: 600; }
.consumo-row-gasto { font-size: var(--t-label); font-weight: 600; color: var(--c-info); }
.consumo-row-qty { display: flex; flex-shrink: 0; align-items: center; gap: var(--s2); }
/* 6rem holds "1234,56" and the spinner at both tiers; 9rem was a text field's width for a count (2026-10-20). */
.consumo-row .consumo-row-qty .input { width: 6rem; height: var(--ctl); min-height: var(--ctl); padding: 0 var(--s1); text-align: center; }
/* the unit SYMBOL (un, kg, L, m): min-width lines the inputs up, nowrap keeps it whole; a fixed 2.5rem clipped longer text */
.consumo-row-unit { min-width: 2rem; white-space: nowrap; font-size: var(--t-label); color: var(--ink-3); }
.consumo-rows > * + * { border-top: 1px solid var(--c-line); }
.consumo-fold { border: 1px solid var(--c-line); }
.consumo-fold > .collapse-title { min-height: var(--ctl-l); font-size: var(--t-label); color: var(--ink-3); }

/* ── kit · table scroll ── a data table's wrapper: it scrolls sideways and keeps cells on one line, which beats cells that wrap
   word by word into tall slivers on a phone. :where() keeps specificity at zero, so a cell class with `white-space` opts out. */
.table-scroll { overflow-x: auto; }
:where(.table-scroll .table th, .table-scroll .table td) { white-space: nowrap; }

/* ── shell ── (DS-E E6) Layout.kt + Sidebar.kt, keyed on the shell's semantic names. The shell's older rules (safe areas, the
   mobile drawer's position, the collapsed rail, the bottom bar's tabs) stay in app-components.css until DS-F; these only replace
   the utilities the views emitted. Equal-weight rules in app-components.css's own components come later and win, so nothing here
   sets a property those rules set. */
.app-shell { min-height: 100vh; min-height: 100dvh; }
.app-content { display: flex; flex: 1 1 0%; flex-direction: column; min-width: 0; min-height: 100vh; min-height: 100dvh; background: var(--c-bg-2); }
.app-main { flex: 1 1 0%; width: 100%; overflow-x: clip; }
#content { outline: 2px solid transparent; outline-offset: 2px; }
/* the skip link: sr-only until focused, then the filled chip in the top-left corner */
.skip-link { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap;
  border-width: 0; border-radius: var(--radius); background: var(--c-primary); color: var(--c-primary-ink); font-size: var(--t-label);
  line-height: 1.25rem; font-weight: 600; }
.skip-link:focus { position: fixed; top: var(--s3); left: var(--s3); z-index: calc(var(--z-dialog) + 10); width: auto; height: auto; padding: var(--s2) var(--s4); margin: 0;
  overflow: visible; clip: auto; white-space: normal; }
/* phone chrome: the pinned top bar, the bottom bar, the drawer's scrim (shown while #sidebar-toggle is checked) */
.mobile-topbar { position: fixed; top: 0; inset-inline: 0; z-index: var(--z-dialog); background: var(--c-primary); color: var(--c-primary-ink); }
.mobile-bottom-nav { position: fixed; bottom: 0; inset-inline: 0; z-index: var(--z-dialog); }
.shell-icon { width: 24px; height: 24px; }
.topbar-title { white-space: normal; overflow-wrap: anywhere; }   /* the scope is the title (M11): it wraps, never "… · Ve…" */
.mobile-menu-overlay { position: fixed; inset: 0; z-index: var(--z-fab); display: none; background: var(--scrim); }
#sidebar-toggle:checked ~ .mobile-menu-overlay { display: block; }
.back-to-top, .back-to-top:hover { border: 1px solid var(--c-line); background-color: var(--c-bg); box-shadow: var(--shadow-float); }   /* :hover outranks the compat .btn-ghost:hover (0,2,0) */
.confirm-question { white-space: pre-line; }
.push-dialog { width: 24rem; max-width: calc(100vw - 2rem); padding: var(--s5); border: 1px solid var(--c-line); background: var(--c-bg); color: var(--c-ink);
  box-shadow: var(--shadow-float); }
.push-dialog > p { margin-top: var(--s2); }
.push-dialog > .actions { margin-top: var(--s5); }
.push-dialog > .actions > .btn { flex: none; }
/* the sidebar: the drawer below 1024 (shown while #sidebar-toggle is checked), the column from 1024 */
.sidebar-shell { z-index: var(--z-drawer); display: none; flex-direction: column; }
#sidebar-toggle:checked ~ .sidebar-shell { display: flex; }
.sidebar-shell > aside { display: flex; flex-direction: column; width: 100%; background: var(--c-primary); color: var(--c-primary-ink);
  box-shadow: var(--shadow-float); transition: width 300ms cubic-bezier(.4, 0, .2, 1); }
/* two rows (user 2026-10-13): the brand + collapse arrow, then the unidade switcher block when there is one */
.sidebar-brand { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s4);
  border-bottom: 1px solid color-mix(in srgb, var(--c-primary-ink) 10%, transparent); }
.sidebar-brand-row { display: flex; align-items: center; justify-content: space-between; }
.sidebar-logo-link { display: flex; flex: 1 1 0%; min-width: 0; align-items: center; gap: var(--s2); }
.unidade-switcher-caption { padding-inline: var(--s3); }
.unidade-switcher-icon { flex-shrink: 0; }
.sidebar-initial { flex-shrink: 0; width: 2.5rem; height: 2.5rem; object-fit: contain; }
span.sidebar-initial { display: flex; align-items: center; justify-content: center; background-color: color-mix(in srgb, var(--c-primary-ink) 20%, transparent);
  font-size: var(--t-label); line-height: 1.25rem; font-weight: 700; }
.sidebar-company { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.collapse-icon { transition: transform 300ms cubic-bezier(.4, 0, .2, 1); }
.global-search-section { position: relative; padding: var(--s2); border-bottom: 1px solid color-mix(in srgb, var(--c-primary-ink) 10%, transparent); }
.global-search-collapsed-trigger { display: none; width: 100%; align-items: center; justify-content: center; padding-block: var(--s2);
  color: color-mix(in srgb, var(--c-primary-ink) 70%, transparent); }
.global-search-collapsed-trigger:hover { background-color: color-mix(in srgb, var(--c-primary-ink) 10%, transparent); color: var(--c-primary-ink); }
/* the results panel: beside the column from 1024, under the search box in the drawer */
.global-search-section > .global-search-panel { position: absolute; top: 0; left: 100%; z-index: var(--z-dialog); margin-left: var(--s2); width: 26rem;
  max-width: calc(100vw - 14rem); border: 1px solid var(--c-line); background: var(--c-bg); color: var(--c-ink); box-shadow: var(--shadow-raise); }
.global-search-scroll { max-height: 60vh; max-height: 60dvh; overflow-y: auto; overscroll-behavior: contain; }
.sidebar-nav { padding-block: var(--s4); }
.sidebar-shell nav > .menu { gap: var(--s1); }
.sidebar-shell nav :is(a, summary) { gap: var(--s3); }
/* lab 08's section title: t-micro (12px, 600; caps + .06em from 1024 via .t-micro). Restated here: the compat `.menu-title`
   (14px, 700) ties .t-micro at (0,1,0) and comes later, so the role alone loses. */
/* the kit's lab 08 specimen draws the switcher caption on the same bar colour, outside .sidebar-shell (axe contrast) */
.sidebar-shell .menu-title, .kit-brand-specimen .menu-title { padding-top: var(--s4); font-size: var(--t-micro); font-weight: 600;
  line-height: var(--lh-body); color: color-mix(in srgb, var(--c-primary-ink) 60%, transparent); }
.sidebar-shell .menu-title:first-child, .kit-brand-specimen .menu-title:first-child { padding-top: 0; }
.sidebar-sep { margin-block: var(--s2); }
.sidebar-sep > hr { border-color: color-mix(in srgb, var(--c-primary-ink) 10%, transparent); }
.sidebar-badge { border: 0; background-color: color-mix(in srgb, var(--c-primary-ink) 20%, transparent); color: var(--c-primary-ink); }
.sidebar-profile { padding: var(--s4) var(--s4) 0; border-top: 1px solid color-mix(in srgb, var(--c-primary-ink) 10%, transparent); }
.sidebar-foot { padding: var(--s4); }
.sidebar-logout { width: 100%; justify-content: flex-start; gap: var(--s3); color: color-mix(in srgb, var(--c-primary-ink) 70%, transparent); }
.sidebar-logout:hover { color: var(--c-primary-ink); }
.sidebar-logout > .sidebar-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the entry sidebar.ts marks current (data-nav-active-class); :where keeps it one class, so the menu's hover and focus rules still win */
:where(.sidebar-shell) .nav-active { background-color: color-mix(in srgb, var(--c-primary-ink) 10%, transparent); color: var(--c-primary-ink); font-weight: 600; }
/* the search box (sidebar and Ctrl+K dialog): magnifier left, spinner / shortcut right */
.global-search-box { position: relative; }
.global-search-icon { position: absolute; top: 50%; left: .625rem; width: 16px; height: 16px; transform: translateY(-50%); opacity: .7; pointer-events: none; }
.global-search-input { width: 100%; padding-left: 2rem; padding-right: 3.5rem; }
.global-search-loading { position: absolute; top: 50%; right: .625rem; transform: translateY(-50%); }
.global-search-kbd { position: absolute; top: 50%; right: var(--s2); transform: translateY(-50%); }
.global-search-foot { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4); border-top: 1px solid var(--c-line);
  font-size: var(--t-caption); line-height: 1rem; color: var(--ink-3); }
.global-search-hint { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.global-search-open { display: flex; align-items: center; gap: var(--s1); margin-left: auto; white-space: nowrap; }
.global-search-dialog { width: 34rem; max-width: calc(100vw - 2rem); margin-top: 10vh; margin-top: 10dvh; padding: 0; border: 1px solid var(--c-line);
  background: var(--c-bg); color: var(--c-ink); box-shadow: var(--shadow-float); }
.global-search-head { padding: var(--s2); border-bottom: 1px solid var(--c-line); }
@media (max-width: 1023.98px) {
  .global-search-section > .global-search-panel { top: 100%; right: var(--s2); left: var(--s2); width: auto; max-width: none; margin-top: var(--s1); margin-left: 0; }
}
@media (min-width: 1024px) {
  .app-shell { display: flex; }
  .sidebar-shell { display: flex; min-height: 100vh; background: var(--c-primary); }
  .sidebar-shell > aside { width: var(--w-sidebar); box-shadow: none; }
  .sidebar-nav { flex: 1 1 0%; overflow-y: auto; }
}
@media print {
  .mobile-topbar, .mobile-bottom-nav, .sidebar-shell, .back-to-top { display: none !important; }
}
/* ── page: ponto ── (DS-E E4) shapes only the ponto pages draw (admin-only module) and no kit renderer covers yet. */
/* the espelho page's centred column (title + content share it: PontoEspelhoView ESPELHO_COLUMN) */
.ponto-column { width: 100%; max-width: var(--w-form); margin-inline: auto; }
/* the espelho/resumo tables' bordered box (scrolls and keeps cells one line through the kit's .table-scroll) */
.ponto-table { border: 1px solid var(--c-line); border-radius: var(--radius); }
.ponto-ref { font-family: var(--font-mono); }
.ponto-table tfoot { font-weight: 700; }
.ponto-end { text-align: right; }
.ponto-absent { background: var(--c-error-soft); }
/* a table cell that wraps (opts out of the wrapper's nowrap), the desktop observacao column keeps a readable width */
.ponto-wrap { white-space: normal; }
.ponto-obs { min-width: 12rem; }
/* the phone face's sub-line under a merged cell (espelho observacao, resumo counts) */
.ponto-subline { display: block; white-space: normal; line-height: var(--lh-tight); }
.ponto-subline.is-short { max-width: 11rem; }
/* an absent value (unlinked login) and the espelho's closing notes */
.ponto-note { font-style: italic; color: var(--ink-3); }
.ponto-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* KIT-GAP(bordered disclosure): one employee's lazy espelho */
.ponto-fold { background: var(--c-bg); border: 1px solid var(--c-line); }
.ponto-fold > .collapse-title { font-weight: 600; }
/* funcionarios: the selection toolbar above the list */
.ponto-toolbar { border: 1px solid var(--c-line); border-radius: var(--radius); background: var(--g-50); padding: var(--s2) var(--s3); }
.ponto-toolbar > .actions { margin-left: auto; }
/* below 1024 the kit .actions row is nowrap with zero-basis buttons; three batch buttons (Criar, Vincular, Desvincular at L)
   are wider than a 384 phone, so this row takes its own line and wraps, each button at its label's width or more */
@media (max-width: 1023.98px) {
  .ponto-toolbar > .actions { flex-basis: 100%; flex-wrap: wrap; }
  .ponto-toolbar > .actions > .btn { flex: 1 1 auto; }
  /* the row checkbox's hit area grows to 48px tall; the negative margin keeps the box where it sat */
  .ponto-pick-hit { min-height: var(--ctl-l); margin-block: calc((var(--check) - var(--ctl-l)) / 2); }
}
/* funcionarios row: checkbox beside name + cargo (top-aligned on the card), the phone lines indented under the name */
.ponto-pick { display: flex; align-items: flex-start; gap: var(--s3); }
.ponto-pick-hit { display: flex; align-items: center; cursor: pointer; }
.ponto-lines { margin-top: var(--s2); padding-left: calc(var(--check) + var(--s3)); }
/* config list: provedor · login in one cell, the login muted and truncated */
.ponto-provider > * { flex-shrink: 0; }
.ponto-provider > * + * { margin-left: var(--s1); color: var(--ink-3); }
.ponto-provider > :last-child { flex-shrink: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the import/link dialogs' scrolling people list, rows divided */
.ponto-pick-list { max-height: 13rem; overflow-y: auto; border: 1px solid var(--c-line); border-radius: var(--radius); font-size: var(--t-label); }
.ponto-pick-list.is-tall { max-height: 20rem; }
.ponto-pick-list > * + * { border-top: 1px solid var(--g-100); }
ul.ponto-pick-list { padding: var(--s2); }
ul.ponto-pick-list > li { padding: var(--s1) 0; }
.ponto-link-row { gap: var(--s2); align-items: start; padding: var(--s2); }
@media (min-width: 1024px) {
  .ponto-pick { align-items: center; }
  /* funcionarios: nome, matricula, cpf, status, login, acoes (PontoFuncionariosView) */
  .ponto-funcionarios-list-cols { grid-template-columns: minmax(0,1fr) minmax(0,10rem) minmax(0,8.5rem) minmax(0,8rem) minmax(0,8rem) minmax(0,var(--list-actions-w)); }
}
/* ── page: financeiro ── (DS-E E4) the yearly report (FinanceiroReportView): phone = month cards, 1024+ = the month table. */
/* the page column (filter, sections), the sections (24 apart) and one currency section: their own flex gap, no --gap,
   so no bare kit stack/cluster below them inherits a page spacing (C6 trap) */
.financeiro-report, .financeiro-sections, .financeiro-section { display: flex; flex-direction: column; gap: var(--s4); }
.financeiro-sections { gap: var(--s5); }
/* base segments + year select: stacked on the phone (segments full width), one row from 1024 */
.financeiro-filter { display: flex; flex-direction: column; gap: var(--s2); }
.financeiro-filter > .segments { width: 100%; }
.financeiro-kpi-value { color: var(--c-primary); }
/* a phone month card: name + valor, the counts line, the closed-orcamento disclosure */
.financeiro-month { padding: var(--s3); border: 1px solid var(--c-line); }
.financeiro-month > details { margin-top: var(--s2); }
.financeiro-counts { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); margin-top: var(--s1); }
/* a plain <details> summary: 8px hit padding that does not move the layout */
.financeiro-disclosure { cursor: pointer; padding-block: var(--s2); margin-block: calc(-1 * var(--s2)); }
/* the phone list of a month's closed orcamentos: a line between rows, each row the link (48px), stacked —
   número (ink, bold, wraps never cut: M28) + valor (right, tabular) over the row's own Exec./Manut. in the month (ink-2) */
.financeiro-fechamentos { margin-top: var(--s2); font-size: var(--t-label); color: var(--c-ink); }
.financeiro-fechamentos > li + li { border-top: 1px solid var(--c-line); }
.financeiro-fechamentos .financeiro-fechamento { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s2); min-height: var(--ctl-l); padding-block: var(--s2); }
.financeiro-fechamentos .financeiro-fechamento:hover { background: var(--g-50); }
.financeiro-fechamentos .financeiro-fechamento > :first-child { flex-basis: 100%; min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.financeiro-fechamentos .financeiro-fechamento > .num { margin-left: auto; text-align: right; white-space: nowrap; }
.financeiro-fechamentos .financeiro-fechamento > .financeiro-counts { flex-basis: 100%; margin-top: 0; color: var(--ink-2); }
/* the month table: card frame, figures right (valor) / centred (counts), body cells top-aligned beside an open month */
.financeiro-table { background: var(--c-bg); border: 1px solid var(--c-line); border-radius: var(--radius); }
.financeiro-table :where(th, td):nth-child(2) { text-align: right; }
.financeiro-table :where(th, td):nth-child(n+3) { text-align: center; }
.financeiro-table tbody td { vertical-align: top; }
.financeiro-scroll { overflow-x: auto; }
/* an open month's orcamentos (desktop): rows of the month table itself (one tbody per month), so each figure sits in the
   month's own column and sums to it (user 2026-10-26/27). Months stripe per tbody; a closed month's disclosure hides its
   rows. In the Mês cell the número (ink, 600, wraps). */
.financeiro-table tbody:nth-of-type(even) { background: var(--g-100); }
.financeiro-month-group:has(> tr > td > details:not([open])) > .financeiro-fechamento-row { display: none; }
.financeiro-fechamento-row { color: var(--c-ink); font-size: var(--t-label); }
.financeiro-fechamento-row:hover { background: var(--g-50); }
.financeiro-table .financeiro-fechamento-row > td { padding-block: var(--s2); border-top: 1px solid var(--c-line); }
.financeiro-table .financeiro-fechamento-row > td:first-child { padding-left: calc(1rem + var(--s5)); }
.financeiro-fechamento-cell { display: flex; gap: var(--s3); }
.financeiro-fechamento-cell > a { min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
@media (min-width: 1024px) {
  .financeiro-filter { flex-direction: row; align-items: center; }
  .financeiro-filter > .segments { width: auto; }
}
/* ── page: mapa ── (DS-E E4) the device trajeto page (MapaViews): calendar column + map column. Leaflet's own colours
   live in mapa.ts (canvas, G3-exempt); these are the page's boxes. */
/* calendar + map: a column on the phone, a row from 1024; its own gap, no --gap for anything below to inherit (C6 trap) */
.mapa-layout { display: flex; flex-direction: column; gap: var(--s4); }
/* the map column: its lines (resumo, qualidade, replay) read at label size in full ink */
.mapa-main { font-size: var(--t-label); }
.mapa-warning { color: var(--c-warning); }
/* the Leaflet mount: a phone-sized slice under the fold; beside the calendar it takes the viewport below the chrome */
.mapa-canvas { width: 100%; height: 60dvh; min-height: 20rem; border: 1px solid var(--c-line); border-radius: var(--radius); }
/* Leaflet's panes (z 400) and controls (z 800–1000) stay inside the map: uncontained they outrank the fixed phone bars (z 50). */
.leaflet-container { isolation: isolate; }
/* a bordered native disclosure (qualidade, calendario); the summary keeps its native marker, so it stays inline */
.mapa-fold { padding: var(--s2) var(--s3); background: var(--c-bg); border: 1px solid var(--c-line); border-radius: var(--radius); }
.mapa-fold > summary { cursor: pointer; -webkit-user-select: none; user-select: none; }
.mapa-fold > ul { margin-top: var(--s1); }
.mapa-calendario { padding: var(--s3); }
.mapa-calendario > summary { font-weight: 600; }
.mapa-calendario > summary > .badge { margin-left: var(--s2); }
/* phone tap floor (M3 48px): the summaries stay block (a flex summary drops the native marker), so min-height plus
   align-content; the negative margin spends the details' own padding, so a closed fold is 48px tall (was 40) */
@media (max-width: 1023.98px) {
  .mapa-fold > summary, .mapa-calendario > summary { min-height: var(--ctl-l); align-content: center; }
  .mapa-fold > summary { margin-block: calc(-1 * var(--s2)); }
  .mapa-calendario > summary { margin-block: calc(-1 * var(--s3)); }
}
/* the month grid under the calendar summary */
.mapa-mes { margin-top: var(--s3); width: 100%; }
.mapa-mes table { width: 100%; max-width: 28rem; border-collapse: collapse; }
.mapa-mes :where(th, td) { padding: var(--s1); text-align: center; }
.mapa-mes th { font-weight: 400; }
.mapa-mes td > span { color: var(--ink-3); }
.mapa-dia { width: 100%; }
.mapa-dia[aria-current="page"] { background: var(--g-200); font-weight: 700; }
/* the replay strip: mapa.ts drops `hidden` once the feed has a ponto (a display rule would otherwise beat [hidden]) */
.mapa-replay[hidden] { display: none; }
.mapa-replay > label { font-weight: 600; }
.mapa-replay > p { flex-basis: 100%; }
/* the day timeline: one focusing button per stop, trip and signal gap */
.mapa-linha { width: 100%; }
.mapa-linha button { display: flex; width: 100%; min-height: var(--ctl-l); align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: var(--radius); font-size: var(--t-label); text-align: left; }
.mapa-linha button:hover { background: var(--g-100); }
@media (min-width: 1024px) {
  .mapa-layout { flex-direction: row; align-items: flex-start; }
  .mapa-side { flex-shrink: 0; }
  .mapa-canvas { height: calc(100dvh - 13rem); }
  .mapa-mes { width: max-content; }
  .mapa-linha { width: 18rem; }
}
/* ── page: contrato ── (DS-E E4) shapes only the contrato pages draw and no kit renderer covers yet. */
/* a machine string (cofre UUID, webhook URL): monospace, broken anywhere so the whole value shows at every width */
.contrato-code { font-family: var(--font-mono); overflow-wrap: anywhere; }
/* a long unbroken value (e-mail, cliente name) wraps instead of spilling into the next column */
.contrato-wrap { overflow-wrap: anywhere; }
/* a documento number (list caption under the cliente): one unbroken run, never split at its own dots and dash */
.contrato-doc { white-space: nowrap; }
/* the phone card's status badge keeps its width beside a wrapping numero */
.contrato-status { flex-shrink: 0; }
/* the valor-drift alert under the contract value: the compact padding of an inline notice */
.contrato-drift { padding: var(--s2); }
/* the config form's cofre UUID input + "Listar cofres" probe: stacked on the phone, one row from 1024 */
.contrato-cofre-row { display: flex; flex-direction: column; gap: var(--s2); }
.contrato-cofre-row > :first-child { min-width: 0; }
.contrato-cofre-row .input { width: 100%; }
@media (min-width: 1024px) {
  .contrato-cofre-row { flex-direction: row; align-items: flex-start; }
  .contrato-cofre-row > :first-child { flex: 1 1 auto; }
  /* contrato list (F8): numero, cliente (+ telefone · documento under the name), valor, status, acoes (ContratoListView). The
     numero track is 11rem (was 14rem/18%: at 1920 an 11rem track holds "8883 (Proposta Atualizada)" on one line while
     14rem gave a 4-digit number 274 px, user 2026-10-14); the stored free text still WRAPS in it, never ellipses (house rule:
     width never hides information, R2 2026-10-14); capped at 16% of the row like the orçamento tracks, because at
     1024 a full track sat empty while the cliente wrapped onto four lines (walk 2026-10-14). The acoes track holds the two
     row icons (`.row-actions`, F1): two `--ctl` squares, 48px under a coarse pointer, plus the cell's --s1 inset = 104px.
     At 1024 (774px of row) the fixed tracks leave the cliente ~259px; cliente is the list's TEXT column and keeps the
     elastic 1fr — the window's spare width belongs to it, not to a number (A, user 2026-10-14). */
  .contrato-list-cols { grid-template-columns: minmax(0,min(11rem,16%)) minmax(0,1fr) minmax(0,8rem) minmax(0,9rem) minmax(0,var(--list-actions-w)); }
}
/* ── page: estoque ── (DS-E E3) estoque, pedidos and conferencia shapes no kit renderer covers. Phone base, desktop from 1024.
   Classes after the list kit's on purpose: a muted or centred cell is a `.list-cell` modifier and must win at (0,1,0). */
/* list rows: the saldo figure, a muted/centred cell, the primary cell's phone rhythm, the save-redirect anchor */
.estoque-saldo { font-weight: 700; }
.estoque-saldo.is-falta { color: var(--c-error); }
.estoque-muted { color: var(--ink-3); }
.estoque-cell-center { justify-content: center; }
/* the list header over a centred column (EstoqueListView headers; the kit pads it) */
.estoque-head-center { text-align: center; }
.estoque-primary { gap: var(--s1); padding-bottom: var(--s3); }
.estoque-anchor { scroll-margin-top: calc(var(--h-topbar) + var(--s6)); }
.estoque-meta { color: var(--ink-2); }
/* "· Automatico" beside the card title: caption weight, never the title's 600, kept on one line */
.estoque-pedido-auto { font-weight: 400; white-space: nowrap; }
/* the sign alone takes the hue (M15 amended 2026-10-01): `ink-success` / `ink-error`, never the ink-3 this used to pin here */
.estoque-sign { font-weight: 700; }
/* the card footer's Entrada/Saida halves, 16px apart (M5); (0,2,0) beats app-components.css's later `.actions` gap */
.actions.estoque-lancar { gap: var(--s4); padding: 0 var(--s4) var(--s4); }
/* the desktop pair: same M5 16px as the phone's, not `.actions`' default 8px — two bare signs 8px apart
   read as one control (user 2026-10-14) */
.actions.estoque-cell-center { gap: var(--s4); flex-wrap: nowrap; }
/* the falta line and the lancamento-blocked hint (KIT-GAP: alert renderer, as orcamento-alert) */
.estoque-falta { width: 100%; color: var(--c-warning); }
.estoque-blocked-hint { display: flex; align-items: center; gap: var(--s3); width: 100%; margin-bottom: var(--s4);
  padding-block: var(--s3); text-align: left; }
/* extrato: a movement's sign colour, the phone card's line rhythm */
.estoque-qty { font-weight: 600; }
.estoque-qty.is-in { color: var(--c-success); }
.estoque-qty.is-out { color: var(--c-error); }
.estoque-extrato-primary { gap: var(--s3); }
/* categorias: the card, one bordered tile per categoria */
.card.estoque-categorias { background: var(--c-bg); }
.estoque-categorias > .card-body { gap: var(--s4); }
.estoque-categoria { padding: var(--s4); background: var(--g-50); border: 1px solid var(--c-line); border-radius: var(--radius); }
/* text over its action on the phone, side by side from 1024 (categoria tile, composicao head, frequent-item row) */
.estoque-split { display: flex; flex-direction: column; gap: var(--s3); }
/* a help line over a section's rows, or the row it shares with the section's add button */
.estoque-help { margin-bottom: var(--s3); font-size: var(--t-label); }
.estoque-help > .actions { flex-shrink: 0; }
.estoque-note { font-style: italic; }
.estoque-pre { white-space: pre-line; }
.estoque-head-line { margin-top: var(--s2); }
/* pedido detail: the phone item rows (the desktop table's every column, two lines each) */
.estoque-item-rows { padding: 0 var(--s3); }
.estoque-item-rows > * { padding: var(--s3) 0; }
.estoque-item-rows > * + * { border-top: 1px solid var(--c-line); }
.estoque-item-rows .between { align-items: flex-start; }
.estoque-item-rows .badge { flex-shrink: 0; }
/* carga padrao: the Equipes | Matrizes | Filiais strip, one horizontal bar at every width (three stacked 48px rows
   on the phone were ~150px before the first row, user 2026-10-20); the current tab is its aria-selected */
.estoque-tipo-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; margin-bottom: var(--s3); padding: var(--s1);
  background: var(--c-bg-2); border: 1px solid var(--c-line); border-radius: var(--radius); }
.estoque-tipo-tab { display: flex; align-items: center; justify-content: center; min-height: var(--ctl-l); padding: var(--s2) var(--s3);
  font-size: var(--t-caption); font-weight: 600; text-align: center; color: var(--ink-3); border-radius: var(--radius);
  text-decoration: none; transition: background-color .15s, color .15s; }
.estoque-tipo-tab:hover { color: var(--c-ink); }
.estoque-tipo-tab[aria-selected="true"] { background: var(--c-bg); color: var(--c-primary); box-shadow: var(--shadow-rest); }
/* carga padrao rows: a stacked block on the phone, a row of `.carga-padrao-list-cols` from 1024 */
/* phone density as before DS-E (low-literacy users, no taller rows): tight lines, 4px only above the input */
.estoque-carga-row { display: flex; flex-direction: column; gap: 0; padding: var(--s3) 0; border-bottom: 1px solid var(--c-line); }
.estoque-carga-row:last-child { border-bottom: 0; }
.estoque-carga-item, .estoque-carga-cell { padding: 0 var(--s4); }
.estoque-carga-item { font-weight: 600; line-height: var(--lh-tight); }
.estoque-carga-cell.t-label { line-height: var(--lh-tight); }
.estoque-carga-row > .form-control { margin-top: var(--s1); }
.estoque-carga-hint { margin-top: var(--s3); }
/* item form: the name field's suggestion dropdown, the kit recipe rows and their empty note */
.estoque-nome { position: relative; }
.estoque-suggest { position: absolute; top: 100%; left: 0; right: 0; z-index: var(--z-drawer); margin-top: var(--s1); }
.estoque-suggest-list { max-height: 15rem; overflow-y: auto; background: var(--c-bg); border: 1px solid var(--c-line);
  border-radius: var(--radius); box-shadow: var(--shadow-raise); }
@media (max-width: 1023.98px) {
  /* M30, as .combobox-dropdown: the suggestions flow in the page, no inner scroll box, nothing under the bottom nav */
  .estoque-suggest { position: static; }
  .estoque-suggest:empty { display: none; }   /* in flow now: the empty #item-suggestions must not leave its margin */
  .estoque-suggest-list { max-height: none; overflow: visible; }
}
.estoque-composicao-row { display: grid; gap: var(--s2); padding: var(--s3); background: var(--c-bg); border: 1px solid var(--c-line); }
.estoque-composicao-empty { padding: var(--s3) var(--s4); font-size: var(--t-label); font-style: italic; color: var(--ink-3);
  border: 1px dashed var(--c-line); }
/* lancamento form: the live saldo line, the empty-bin hint */
.estoque-saldo-line { margin-top: var(--s1); }
.estoque-saldo-line > span + span { margin-left: var(--s3); }
.estoque-bin-vazio { margin-top: var(--s2); color: var(--c-warning); }
/* pedido form: an item row (frequent ones tinted), its quantity area and stepper, a read-only value */
.estoque-pedido-item { display: grid; gap: var(--s3); padding: var(--s3); border: 1px solid var(--c-line); border-radius: var(--radius); }
.estoque-pedido-item.is-frequent { background: var(--g-50); }
.estoque-pedido-item-grid { display: grid; gap: var(--s3); }
.estoque-qty-area { width: 100%; }
/* estoque.ts syncChecklistInput: an unticked pedido row dims its quantity field and stops taking clicks (was opacity-40 pointer-events-none) */
.estoque-qty-area.is-off { opacity: .4; pointer-events: none; }
.estoque-stepper { width: 100%; }
.estoque-stepper > .input { flex: 1 1 0%; min-width: 0; width: 100%; padding: 0 var(--s1); text-align: center; }
.input.estoque-readonly { background: var(--c-bg-2); }
.estoque-fold-body { padding: var(--s3); }
/* conferencia: the gate banner, the historico phone counts, the confirmada cell, the detail's lines heading */
.conferencia-gate { margin-bottom: var(--s2); }
/* the explicit pair beats the cluster's inherited --gap; no gap-N modifier in the markup (Tailwind's gap-3 would win) */
.conferencia-counts { column-gap: var(--s3); row-gap: var(--s1); }
.conferencia-confirmada { white-space: nowrap; }
.conferencia-linhas-head { margin-top: var(--s4); }
@media (min-width: 1024px) {
  .estoque-split { flex-direction: row; align-items: center; justify-content: space-between; }
  .estoque-split.is-top { align-items: flex-start; }
  .estoque-tipo-tabs { display: inline-grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: auto; }
  .estoque-tipo-tab { min-height: var(--ctl-s); }
  .estoque-carga-row { display: grid; align-items: center; }
  .estoque-carga-row > .form-control { margin-top: 0; }
  .estoque-carga-item { font-weight: 400; }
  .estoque-composicao-row { grid-template-columns: minmax(0, 1fr) 8rem auto; align-items: end; }
  .estoque-pedido-item-grid { grid-template-columns: minmax(0, 1fr) 10rem auto; align-items: end; }
  .estoque-qty-area { width: 11rem; }
  /* extrato: quantidade, saldo acumulado, observacoes, retirado por, acoes (EstoqueExtratoCatalogoView) */
  .extrato-list-cols { grid-template-columns: minmax(0,8rem) minmax(0,8rem) minmax(0,1fr) minmax(0,12rem) minmax(0,6rem); }
  /* historico: equipe, tipo, pessoas, respondidas, faltas, divergencias, confirmada (ConferenciaHistoricoView) */
  .conferencia-historico-list-cols { grid-template-columns: minmax(0,1.2fr) minmax(0,0.7fr) minmax(0,0.5fr) minmax(0,0.7fr) minmax(0,0.5fr) minmax(0,0.8fr) minmax(0,1.2fr); }
}
/* ── page: servico ── (DS-E E2) */
/* The crew board (ServicoBoardView). Phone (base): one day across every crew, a section per crew, the day strip in the
   toolbar. Desktop: the week grid, a 3rem day gutter + one 20rem column per crew, scrolled sideways. The phone card is kept
   exactly as the user approved it (11d1221d): ⋮ inside top-right, tipo-coloured left edge, número / cliente / endereço /
   time. 6px steps are the board's own (it predates the lab); `calc(var(--s1) * 1.5)` keeps them. */
.servico-tipo-execucao   { --tipo: var(--c-info); }
.servico-tipo-manutencao { --tipo: var(--c-warning); }
.servico-tipo-reserva    { --tipo: color-mix(in srgb, var(--c-neutral) 60%, transparent); }
.legend-swatch--stripe:is(.servico-tipo-execucao, .servico-tipo-manutencao, .servico-tipo-reserva) { background: var(--tipo); }
.servico-board-today { background: color-mix(in srgb, var(--c-primary) 5%, transparent); }
.servico-board-name { font-size: var(--t-body); line-height: var(--lh-body); font-weight: 700; }
.servico-board-count { margin-left: auto; white-space: nowrap; line-height: calc(var(--t-caption) * 4 / 3); }
/* phone: the day strip (seven chips) and one section per crew */
.servico-board-strip { margin-top: var(--s2); }
.btn.servico-board-chip { flex: 1 1 0%; min-width: 0; flex-direction: column; gap: 0; padding-inline: 0; line-height: var(--lh-tight); }
.servico-board-chip > .t-micro { color: inherit; }
.servico-board-chip > .num { font-size: var(--t-label); line-height: calc(var(--t-label) * 10 / 7); }
/* Selected today keeps the filled chip's g-0 ink (primary on the g-900 fill is 1.6:1); bold still marks it as today. */
.actions .btn.servico-board-chip.is-today { font-weight: 700; }
.actions .btn.servico-board-chip.is-today:not(.btn-active) { color: var(--c-primary); }
.servico-board-crew { margin-bottom: var(--s3); }
.servico-board-crew-head { display: flex; align-items: baseline; gap: var(--s2); border-bottom: 2px solid var(--c-line); }
.servico-board-items { display: flex; flex-direction: column; gap: calc(var(--s1) * 1.5); padding-block: calc(var(--s1) * 1.5); }
.servico-board-item { position: relative; }
.servico-board-item > .servico-board-card { padding-right: var(--s7); }
.servico-board-kebab { position: absolute; top: var(--s1); right: var(--s1); }
/* desktop: the week grid */
.servico-board-scroll { overflow-x: auto; padding-bottom: var(--s2); }
.servico-board-grid { min-width: max-content; }
.servico-board-day { width: 3rem; flex-shrink: 0; }
.servico-board-lane { width: 20rem; flex-shrink: 0; }
.servico-board-head { display: flex; border-bottom: 2px solid var(--c-line); }
.servico-board-lane-head { display: flex; align-items: baseline; gap: var(--s2); padding: 0 var(--s2) calc(var(--s1) * 1.5);
  border-left: 1px solid var(--c-line); }
.servico-board-row { display: flex; border-bottom: 1px solid var(--c-line); }
.servico-board-cell { display: flex; flex-direction: column; gap: calc(var(--s1) * 1.5); min-width: 0; padding: calc(var(--s1) * 1.5);
  border-left: 1px solid var(--c-line); }
/* the day gutter: weekday over the day number, which is the create link */
.servico-board-gutter { padding: var(--s2) var(--s1) 0; line-height: var(--lh-tight); color: var(--ink-3); }
.servico-board-gutter.is-today { color: var(--c-primary); font-weight: 700; }
.servico-board-gutter > .t-micro { display: block; color: inherit; }
.servico-board-daylink { display: block; border-radius: var(--radius); font-size: var(--t-title); font-weight: 600; color: inherit;
  text-decoration: none; }
.servico-board-daylink:hover { background: var(--g-100); color: var(--c-primary); }
/* an empty cell: a dash on a weekend, "livre" on a workday */
.servico-board-empty { padding: calc(var(--s1) / 2) var(--s2); line-height: calc(var(--t-caption) * 4 / 3); }
.servico-board-empty.is-free { border-radius: var(--radius); background: var(--c-success-soft); color: var(--c-success); }
/* the card (and the continuation line, the same chrome): the tipo edge, the warning ring while awaiting validation */
.servico-board-card { display: block; padding: calc(var(--s1) * 1.5) var(--s2); background: var(--c-bg); border: 1px solid var(--c-line);
  border-left: 4px solid var(--tipo, var(--c-line)); border-radius: var(--radius); color: inherit; text-decoration: none; }
.servico-board-card:hover { box-shadow: var(--shadow-raise); }
.servico-board-card.is-awaiting { box-shadow: 0 0 0 1px var(--c-warning); }
.servico-board-card.is-awaiting:hover { box-shadow: 0 0 0 1px var(--c-warning), var(--shadow-raise); }
.servico-board-numero { display: flex; align-items: baseline; gap: var(--s2); font-weight: 700; }
.servico-board-numero > .t-caption { font-weight: 600; }
.servico-board-cliente, .servico-board-line { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.servico-board-cliente { font-weight: 600; }
.servico-board-line, .servico-board-meta, .servico-board-tail { line-height: calc(var(--t-caption) * 4 / 3); }
.servico-board-meta { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--s1) * 1.5); margin-top: var(--s1); }
.servico-board-meta > .t-label, .servico-board-tail > .t-label { white-space: nowrap; }
.servico-board-tail { margin-top: var(--s1); }
.servico-board-time { font-family: var(--font-mono); }
.servico-board-legend { margin-top: var(--s2); }
/* the detail page (ServicoDetailView): the header's tipo · status line, the cliente field row (four from 1024), the free-text
   paragraphs, the linked-record cards. KIT-GAP: the four-up field row and the free-text paragraph repeat on OrcamentoDetailView. */
.servico-facts { margin-top: var(--s2); }
.servico-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4) var(--s5); }
@media (min-width: 1024px) { .servico-fields { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.servico-text { font-size: var(--t-label); white-space: pre-line; overflow-wrap: break-word; }
.servico-link-card { padding: var(--s4); border: 1px solid var(--c-line); }
.servico-link-card > p + p { margin-top: var(--s1); }
.servico-link-card > .actions { margin-top: var(--s2); }
/* the form (ServicoFormView): the orçamento combobox sits on its row's baseline; the cor swatches dim while "follow the tipo" is
   ticked; the execution date's help line */
.servico-orcamento-field { align-self: flex-end; }
.servico-cor:has([data-choice-name="usarCorTipo"] input[value="true"]:checked) > .servico-cor-swatches { opacity: .4; pointer-events: none; }
.servico-hint { margin: var(--s1) 0 0 var(--s1); }
/* the fotos-depois panel (ServicoFotosDepoisView): one bordered fold per regiao (KIT-GAP: bordered disclosure), its report and
   "antes" blocks, and the progress bar's own padding over the sticky bar's */
.servico-regiao { border: 1px solid var(--c-line); background: var(--c-bg); margin-bottom: var(--s2); }
.servico-regiao-block { margin-bottom: var(--s3); }
.sticky-action-bar.servico-progresso { padding: var(--s2) var(--s1); }
/* the obra-rápida card (ServicoObraRapidaView, inside the orçamento detail): linked rows, then the ruled "Dias de obra" block */
.servico-obra-list { margin-top: var(--s2); }
.servico-obra-create { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--c-line); }
.servico-obra-create > .actions { margin-top: var(--s2); }
.servico-obra-form { margin-top: var(--s2); }
.servico-obra-form > .actions { margin-top: var(--s4); }
.servico-obra-hint { margin-top: var(--s1); }
.servico-obra-note { margin-top: var(--s2); }
.servico-list-head { display: flex; flex-wrap: wrap; align-items: baseline; }   /* the phone card line 1: número · cliente on one baseline */
/* ── page: agendamento ── (DS-E E2) */
/* The list (AgendamentoListView): the desktop tracks — data, cliente, localização, endereço, motivo, ações — and the phone
   card's lines: date · time (+ the pendente flag) over the motivo, then cliente, local, address and the two attributions.
   A: localização (the short checkbox group joined into a label) is bounded at 14rem and the spare width is split between
   cliente and endereço, the two text columns (1.1fr : 1.4fr — the endereço is the longer line). It was 0.8fr, which at
   1920 gave "Banheiro" a 340 px column while the endereço wrapped. */
@media (min-width: 1024px) {
  .agendamento-list-cols { grid-template-columns: minmax(0,10rem) minmax(0,1.1fr) minmax(0,14rem) minmax(0,1.4fr) minmax(0,7rem) minmax(0,var(--list-actions-w)); }
}
.list-primary.agendamento-primary { gap: var(--s4); }
.agendamento-row-head { align-items: flex-start; }
.agendamento-time { font-weight: 400; }
/* the quote's número is the visit's identifier: quieter than the date, stronger than the time beside it */
.agendamento-row-numero { font-weight: 600; font-variant-numeric: tabular-nums; }
.agendamento-motivo { font-size: var(--t-label); font-weight: 600; text-align: right; }
.agendamento-motivo.is-reuniao { color: var(--c-error); }
.agendamento-card-lines { font-size: var(--t-label); }
.agendamento-local { color: var(--ink-2); }
.agendamento-attrib { gap: var(--s1) var(--s3); }
/* the detail page (AgendamentoDetailView): the motivo under the title, a section body's 8 px under its head, the cliente name
   link, the e-mail value, the "+N" overflow line, the contrato número/status, the section CTAs, the free-text observações */
.agendamento-facts { margin-top: var(--s2); font-weight: 600; color: var(--ink-3); }
.agendamento-body { margin-top: var(--s2); }
.agendamento-triagem { margin-top: var(--s4); }
.link.agendamento-cliente { margin-top: var(--s3); font-size: var(--t-body); font-weight: 600; overflow-wrap: break-word; }
/* the phone face is the kit's `.link-value` row; from 1024 an inline-block so the margin-top holds */
@media (min-width: 1024px) { .link.agendamento-cliente { display: inline-block; } }
.agendamento-email { font-size: var(--t-label); word-break: break-all; }
.agendamento-overflow { margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--c-line); }
.agendamento-numero { font-size: var(--t-body); font-weight: 600; }
.agendamento-status { margin-top: var(--s1); }
.agendamento-cta { margin-top: var(--s2); }
.agendamento-cta.is-spaced { margin-top: var(--s4); }
.agendamento-text { font-size: var(--t-label); white-space: pre-line; }
/* the form (AgendamentoFormView): the logistics spinner dissolves into the grid, so while idle it is no flex item and holds no band
   (a reserved row cost one grid gap plus its own height above Cliente); loading, it takes a line of its own at the right */
.agendamento-spinner-row { display: contents; }
.agendamento-spinner-row > .htmx-indicator { margin-inline-start: auto; }
/* ── page: maquina ── (DS-E E2) */
/* The two lists' card head (número + badge/date, top-aligned); the detail page's section bodies, histórico text, the peças rows
   and the calibragem sensor grid (one column on the phone, five from 1024). */
.maquina-row-head { align-items: flex-start; }
.maquina-body { margin-top: var(--s2); }
.maquina-text { white-space: pre-line; color: var(--ink-2); }
.maquina-peca { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2); padding: var(--s3);
  border: 1px solid var(--c-line); border-radius: var(--radius); }
.maquina-calibragem { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); margin-top: var(--s2); }
/* the manutenção form's message slot stays a block: empty, the form-flow margin collapses through it (a flex box would not) */
.maquina-messages > * + * { margin-top: var(--s2); }
@media (min-width: 1024px) {
  .maquina-calibragem { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
/* ── page: carro ── (DS-E E2) */
/* The list card head (frota + placa badge, top-aligned); the detail page's marca/modelo line, section bodies, the next-entrega
   line, the new/continue CTA and the vistoria history rows (filled, positioned for the creator strip); the checklist screen's
   header block, the avaria panel (error-ruled) and the per-item photo head. */
.carro-row-head { align-items: flex-start; }
.carro-facts { margin-top: var(--s1); color: var(--ink-3); }
.carro-body { margin-top: var(--s2); }
.carro-entrega { margin-bottom: var(--s3); }
.carro-entrega-date { font-size: var(--t-label); font-weight: 600; }
.carro-cta { margin-bottom: var(--s3); }
.carro-vistoria { position: relative; gap: 0; padding: var(--s3) var(--s3) var(--s3) var(--s4); background: var(--g-100); }
.carro-vistoria-meta { font-size: var(--t-label); }
.carro-avaria { margin-top: var(--s1); padding-left: var(--s3); border-left: 4px solid var(--c-error); }
.carro-avaria-tipo { max-width: 20rem; }
.carro-avaria-foot { gap: var(--s4); }
.carro-fotos-head { margin-bottom: var(--s1); }
/* ===== DS-E E9 · ts: DOM the TypeScript modules build, where no kit renderer emits it (rule b, one class per shape) ===== */
/* ── page: offline ── */
.offline-help { font-size: var(--t-label); }
/* ── ts: offline queue (offlineQueue.ts renderItem/renderSummary) — one local change per card on /offline ── */
.offline-item { border: 1px solid var(--c-line); background: var(--c-bg); }
.offline-item-head { display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4); border-bottom: 1px solid var(--g-100); }
.offline-item-path { word-break: break-all; }
.offline-item-error { color: var(--c-error); }
.offline-item-body { --gap: var(--s4); padding: var(--s4); }
/* a fact's label sits on its value (s1); the facts themselves keep the body's s4 rhythm on a desktop and halve it stacked on a phone */
.offline-item-facts { row-gap: var(--s2); }
.offline-item-facts dt { font-weight: 600; color: var(--c-ink); }
.offline-item-facts dd { margin-top: var(--s1); }
.offline-item-fields { border: 1px solid var(--c-line); background: var(--c-bg); }
.offline-item-fields > .collapse-title { font-size: var(--t-label); font-weight: 600; }
.offline-tile { background: var(--g-100); padding: var(--s3); min-width: 0; }
.offline-field { font-size: var(--t-label); overflow-wrap: break-word; }
.offline-field > .t-caption { margin-bottom: var(--s1); font-weight: 600; }
.offline-files > p { margin-bottom: var(--s1); font-weight: 600; color: var(--c-ink); }
.offline-files ul { list-style: disc; padding-left: var(--s4); }
.offline-files li + li { margin-top: var(--s1); }
.offline-stats { width: 100%; box-shadow: var(--shadow-rest); }
.offline-stats .stat-value[data-tone="warning"] { color: var(--c-warning); }
.offline-stats .stat-value[data-tone="info"] { color: var(--c-info); }
@media (min-width: 1024px) {
  .offline-item-head { flex-direction: row; align-items: flex-start; justify-content: space-between; }
}
/* ── ts: pending infiltrações (pendingInfiltracoes.ts) — the queued cards are the server card's twin (.orcamento-card) ── */
.pending-infiltracoes { margin-bottom: var(--s4); }
/* ── ts: annotate (infiltracao.ts) — the ✎ dims while the annotator opens (`data-annotating`) and, as a non-control, on a
   pick the browser cannot decode (HEIC, video: `aria-disabled`) ── */
.btn[data-annotating], span.btn.media-thumb-ann[aria-disabled="true"] { opacity: .5; pointer-events: none; }
/* ── ts: mapa (mapa.ts) — the empty/error message in the map box, the Leaflet legend and the divIcon glyphs. The marker
   sizes and the swatch colours are data (element.style, CSSOM — CSP allows it); shape and type live here. ── */
.mapa-message { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
  height: 100%; padding: var(--s4); text-align: center; color: var(--ink-3); }
.mapa-legend { border: 1px solid var(--c-line); border-radius: var(--radius); background: color-mix(in srgb, var(--c-bg) 90%, transparent);
  padding: var(--s1) var(--s2); font-size: var(--t-caption); color: var(--c-ink); }
.mapa-legend-row { display: flex; align-items: center; gap: var(--s2); white-space: nowrap; }
.mapa-legend-glyph { display: inline-block; flex-shrink: 0; width: 16px; text-align: center; line-height: 1; }
.mapa-legend-dot { display: inline-block; flex-shrink: 0; width: 12px; height: 12px; border-radius: 50%; }
.mapa-glyph { display: flex; align-items: center; justify-content: center; line-height: 1; }
.mapa-parada { border-radius: 50%; font-weight: 700; color: var(--c-warning-ink); }
.mapa-rumo { font-weight: 700; color: var(--c-primary); }
.mapa-descartado { color: var(--ink-3); }
/* ── ts: annotator (imageAnnotator.ts buildOverlay) — the full-screen photo editor dialog: one toolbar row, stage, Cancelar · Salvar.
   Opaque (DS-GAPS G-3): a full-screen editor shows nothing of the page behind it, native dialog and no-dialog fallback
   alike. Ghost buttons read light on the dark ground, and a disabled one is a dimmed word, never the kit's grey box (G-2);
   the stage is the flex-1 region the canvas is measured from. ── */
dialog.annotator { display: flex; flex-direction: column; width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0;
  padding: max(var(--s2), env(safe-area-inset-top)) var(--s2) max(var(--s2), env(safe-area-inset-bottom));
  background: var(--g-900); color: var(--c-primary-ink); }
dialog.annotator::backdrop { background: var(--g-900); }
/* no showModal (polyfills.ts): the opaque dialog IS its backdrop — the whole viewport, above the bars (app.css .no-dialog dialog[open] insets it 1rem) */
.no-dialog dialog.annotator[open] { display: flex; inset: 0; margin: 0; max-height: none; z-index: var(--z-dialog); }
.annotator .btn-ghost { color: var(--c-primary-ink); }
.annotator .btn-ghost:disabled { background-color: transparent; color: color-mix(in srgb, var(--c-primary-ink) 45%, transparent); }
/* G-1: one row at both tiers, every control an equal share, icon over word (`.annotator-label`). `.actions.annotator-row`
   (0,2,0) outranks app-components.css `.actions { flex-wrap: wrap }`, which loads later. */
.actions.annotator-row { flex-wrap: nowrap; padding-bottom: var(--s2); }
.annotator-row > .btn, .annotator-row > .menu { flex: 1 1 0; min-width: 0; }
.annotator-row > .btn { flex-direction: column; flex-wrap: nowrap; gap: 2px; padding: 0 var(--s1); }
.annotator-label { font-size: var(--t-caption); line-height: var(--lh-tight); white-space: nowrap; }
/* The phone's Mais: a kit menu whose trigger is the row's last button — same share, same shape, ghost on the dark ground;
   filled while the active tool or mode is one of its rows, so the row never reads "nothing selected". The sheet's rows are
   the kit's menu rows (components.css section 1): a chosen one wears the picked-row tint, a disabled one `menu-disabled`. */
.annotator-row > .menu { display: flex; }
.annotator-more > summary { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; width: 100%;
  height: var(--ctl); min-height: var(--ctl); padding: 0 var(--s1); border-color: transparent; background: transparent; color: inherit; border-radius: var(--radius); }
.annotator-more > summary::after { display: none; }
.annotator-more[open] > summary, .annotator-more[data-active] > summary { background: var(--c-primary); border-color: transparent; }
.annotator-more .menu-panel .annotator-label { font-size: var(--t-label); }
.annotator-more .menu-panel button[aria-pressed="true"] { background: color-mix(in srgb, var(--c-primary) 10%, var(--c-bg)); font-weight: 600; }
.annotator-stage { display: flex; flex: 1 1 0%; align-items: center; justify-content: center; overflow: hidden; }
.annotator-foot { padding-top: var(--s2); }
.annotator-canvas { max-width: 100%; max-height: 100%; box-shadow: var(--shadow-float); }
@media (min-width: 1024px) {
  dialog.annotator { padding-left: var(--s4); padding-right: var(--s4); }
}
/* ── ts: offline shell (serviceWorker.ts renderOfflineShell) — the page the worker serves for an uncached route ── */
.sw-offline { min-height: 100vh; min-height: 100dvh; background: var(--c-bg); }
.sw-offline-main { max-width: 48rem; margin-inline: auto; padding: var(--s4); }
/* ── ts: combobox (combobox.ts highlightOption) — the keyboard-highlighted option is the one `aria-selected` names ── */
.combobox-option[aria-selected="true"] { background: var(--g-100); }
/* ── ts: password toggle (declarativeHandlers.ts initPasswordToggleFallback) — the eye over a bare password input's right end ── */
.password-field { position: relative; }
/* width:100% is load-bearing: `.form-control` is a flex column, so a bare input stretches to the field's
   column — this wrapper takes it out of that direct-child relationship and an input falls back to its
   intrinsic ~247px, while the labelled field beside it fills 743 (user 2026-10-14). */
.password-field > input { width: 100%; padding-right: var(--s7); }
.password-toggle { position: absolute; top: 0; bottom: 0; right: 0; display: flex; align-items: center; justify-content: center; min-width: var(--ctl-l);
  padding: 0 var(--s3); color: var(--ink-3); }
.password-toggle:hover { color: var(--c-ink); }
/* ── ts: form state banner (utils/formStateUi.ts) — the offline/sync line at the top of a form; a draft conflict sets its
   Restaurar · Descartar row beside the message from 1024, under it below ── */
.form-state-banner { font-size: var(--t-label); }
.form-state-banner.is-conflict { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s3); }
/* below 1024 the buttons take the banner's width (the phone row splits it), not their own shrunk content width */
.form-state-banner.is-conflict > .actions { align-self: stretch; }
@media (min-width: 1024px) {
  .form-state-banner.is-conflict { flex-direction: row; align-items: center; justify-content: space-between; }
  .form-state-banner.is-conflict > .actions { align-self: auto; }
}
/* ── ts: toast parts (utils/toast.ts) — the tone icon and the quotable errorRef, a quiet mono line ("Ref: 22fff21a"; also
   under a form-state banner, formStateUi.ts showSyncError) ── */
.toast-icon { stroke: currentColor; }
.toast-ref { display: block; font-family: var(--font-mono); font-size: var(--t-caption); color: var(--ink-3); }
/* ── ts: upload strip (utils/uploadQueue.ts paintUploadTile; int-specs/background-upload U1) — the state of a pending photo as a
   band along the bottom of its tile, over the photo. Words, never colour alone (M6); a failed strip IS the retry button. ── */
.upload-strip { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: var(--s1); min-height: var(--s5);
  margin: 0; padding: var(--s1) var(--s2); border: 0; border-radius: 0; overflow: hidden; text-align: left; font: inherit;
  font-size: var(--t-caption); line-height: var(--lh-tight); font-weight: 600; color: var(--c-primary-ink);
  background: color-mix(in srgb, var(--g-800) 80%, transparent); }
.upload-strip > [data-upload-state-text] { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-strip > svg { width: 16px; height: 16px; flex-shrink: 0; }
.upload-strip > .upload-progress { position: absolute; left: 0; right: 0; bottom: 0; }
.upload-progress { width: 100%; height: 3px; }
.upload-strip[data-state="failed"] { width: 100%; flex-wrap: wrap; cursor: pointer; color: var(--c-error-ink); background: var(--c-error); }
.upload-strip[data-state="failed"] > [data-upload-state-text] { white-space: normal; }   /* `Não enviada · Tentar de novo` wraps on a 115 px tile instead of clipping */
.upload-strip[data-state="failed"]:hover { background: color-mix(in srgb, var(--c-error) 85%, var(--g-900)); }
.upload-strip[data-state="discarded"] { width: 100%; flex-wrap: wrap; }
.upload-strip[data-state="discarded"] > [data-upload-state-text] { white-space: normal; }   /* `Descartada por Ana Lima` wraps on a 115 px tile instead of clipping */
.upload-strip[data-state="sent"] { background: color-mix(in srgb, var(--c-success) 85%, transparent); }
/* the placeholder tile (veda/view/upload/UploadViews.kt uploadPlaceholderTile; U4): a dashed box where the photo will land, in the
   same cell the photo will take. `.media-thumb-img.is-lg` (above) is `display: block`; this later rule of equal weight makes it a column */
.upload-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s1); padding: var(--s2);
  text-align: center; font-size: var(--t-caption); line-height: var(--lh-tight); color: var(--ink-3);
  background: var(--g-50); border: 1px dashed var(--g-300); }
.media-thumb-img.upload-placeholder { display: flex; }
.upload-placeholder > svg { color: var(--g-400); }
/* the card's count line (uploadSummary; U2/U4): `3 fotos · 1 enviando` */
.upload-summary { margin: 0; }
/* the global chip (uploadChip; U3): `↑ 3 fotos` on the primary surface it sits on — the phone top bar, the sidebar brand block */
.upload-chip { display: inline-flex; align-items: center; justify-content: center; gap: var(--s1); min-height: var(--ctl-s); padding: 0 var(--s3);
  border: 0; border-radius: var(--radius); background: color-mix(in srgb, var(--c-primary-ink) 16%, transparent); color: var(--c-primary-ink);
  font: inherit; font-size: var(--t-label); line-height: var(--lh-tight); font-weight: 600; white-space: nowrap; cursor: pointer; }
.upload-chip:hover { background: color-mix(in srgb, var(--c-primary-ink) 24%, transparent); }
.upload-chip[hidden] { display: none; }
.upload-chip-icon { width: 16px; height: 16px; flex-shrink: 0; }
.topbar-upload-chip { margin-left: var(--s2); }
.sidebar-upload-row { width: 100%; }
/* the sheet (uploadSheet + utils/uploadSheet.ts; U3): photos grouped page → item, one row each with its thumb, name and state */
.upload-sheet-list { display: flex; flex-direction: column; gap: var(--s4); }
.upload-group { display: flex; flex-direction: column; gap: var(--s2); }
.upload-group-title { font-size: var(--t-caption); color: var(--ink-3); }
.upload-group-sub { font-size: var(--t-label); font-weight: 600; }
.upload-row { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; column-gap: var(--s3); row-gap: var(--s1); align-items: center; }
.upload-row-thumb { grid-row: 1 / 3; width: 40px; height: 40px; object-fit: cover; border: 1px solid var(--c-line); background: var(--g-100); }
.upload-row-name { grid-column: 2; font-size: var(--t-label); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-row-status { grid-column: 2; font-size: var(--t-caption); color: var(--ink-3); overflow-wrap: anywhere; }
.upload-row-status[data-state="failed"] { color: var(--c-error); }
.upload-row-status > .upload-progress { display: block; margin-bottom: var(--s1); }
.upload-row > .btn { grid-column: 3; grid-row: 1 / 3; height: var(--ctl-l); min-height: var(--ctl-l); }   /* retry + dismiss are the row's one finger target: 48 at every width (user 2026-10-26: 48 is the standard), not .btn-sm's 32 */
.upload-row > .btn-circle { width: var(--ctl-l); }
.upload-sheet-note { font-size: var(--t-caption); color: var(--ink-3); }
.upload-sheet-note[hidden] { display: none; }
/* from 1024 the sheet is a popover beside the sidebar chip, top-aligned with it (left/top come from the chip's box, uploadSheet.ts):
   the kit's centred card is for a question; a queue is glanced at and dismissed */
@media (min-width: 1024px) {
  dialog.sheet.upload-sheet { position: fixed; margin: 0; width: 360px; max-height: calc(100dvh - var(--s7)); border: 1px solid var(--c-line); box-shadow: var(--shadow-raise); }
}
/* ── ts: field message (utils/fieldMessage.ts showFieldMessage) — the browser-side line under a field: an error, or a
   warning that does not block (`data-severity`) ── */
.field-feedback { margin-top: var(--s1); font-size: var(--t-label); color: var(--c-error); }
.field-feedback[data-severity="warning"] { color: var(--c-warning); }
/* ── ts: crop overlay (imageCropOverlay.ts) — positioning shells; geometry and colours are set per drag through CSSOM ── */
.crop-clip { position: absolute; overflow: hidden; }
.crop-rect { position: absolute; }
.crop-handle { position: absolute; display: flex; align-items: center; justify-content: center; }
.crop-dot { border-radius: 50%; }
/* ── ts: agenda drag (agendaDnd.ts, agendaGrid.ts) — the row in hand, the day cell under it, a move in flight ── */
[data-dnd-id][data-dnd-dragging] { opacity: .5; }
/* The ring is an overlay above the day's cards: an inset shadow or outline paints under positioned children, so on a full
   day it showed only in the cards' 4 px margins (2026-10-23). Both marks stay on until the re-fetch lands (agendaDnd.ts drop). */
[data-dnd-over] { position: relative; }
[data-dnd-over]::after { content: ''; position: absolute; inset: 0; z-index: 1; border: 2px solid var(--c-primary); border-radius: inherit; pointer-events: none; }
[data-dnd-busy] { pointer-events: none; opacity: .7; }
/* ── ts: search (globalSearch.ts highlightItem) — the keyboard-highlighted result is the one `aria-selected` names ── */
.search-item[aria-selected="true"] { background: var(--g-100); }
/* ── ts: online only (offline/precacheCoordinator.ts updateOnlineOnlyControls) — a control that needs the network dims offline ── */
[data-requires-online][aria-disabled="true"] { opacity: .5; }
