/*
 * Vaadin-specific part of the TestSys design system. Tokens and .ts-* classes live in testsys-ui/tokens/;
 * this file only maps Lumo onto the tokens and covers DOM that differs from the shared markup.
 */
html {
  --lumo-font-family: var(--font-sans);
  --lumo-primary-color: var(--accent);
  --lumo-primary-text-color: var(--accent);
  --lumo-primary-color-50pct: var(--accent-ring);
  --lumo-error-color: var(--danger);
  --lumo-error-text-color: var(--danger);
  --lumo-success-color: var(--success);
  --lumo-body-text-color: var(--text-primary);
  --lumo-header-text-color: var(--text-primary);
  --lumo-secondary-text-color: var(--text-secondary);
  --lumo-border-radius-m: var(--radius-md);
  --lumo-size-m: var(--control-md);
  --lumo-size-s: var(--control-sm);
  --lumo-size-l: var(--control-lg);
  --lumo-size-xs: var(--control-sm);
  --lumo-space-xs: var(--space-1);
  --lumo-space-s: var(--space-2);
  --lumo-space-m: var(--space-3);
  --lumo-space-l: var(--space-4);
  --lumo-font-size-m: var(--fs-sm);
  --lumo-font-size-s: var(--fs-xs);
  --lumo-font-size-xs: var(--fs-caption);
  --lumo-font-size-xxs: var(--fs-micro);
  --lumo-font-size-l: var(--fs-body);
  --lumo-base-color: var(--surface-card);
}

/* Vaadin wraps inline SVG into a div. */
.ts-icon { display: inline-flex; flex: none; line-height: 0; }

/* Header: Vaadin renders links where the shared markup renders buttons. */
.ts-header__spacer { flex: 1 1 0; min-width: 0; }
.ts-header__action { height: 30px; }
.ts-header__avatar { width: 24px; height: 24px; font-size: var(--fs-micro); }
a.ts-brand:hover, a.ts-nav__item:hover, a.ts-btn:hover { text-decoration: none; }

/* Block titles: override Lumo's header text color to prevent dark-on-dark. */
.ts-block__title { color: inherit; }

/* Actions: roles and sizes of vaadin-button, mirroring .ts-btn variants. */
vaadin-button[data-ts-role] {
  --vaadin-button-height: var(--control-md);
  --vaadin-button-min-width: 0;
  --vaadin-button-padding: 0 var(--space-3);
  --vaadin-button-margin: 0;
  --vaadin-button-border: 1px solid transparent;
  --vaadin-button-border-radius: var(--radius-md);
  --vaadin-button-font-size: var(--fs-sm);
  --vaadin-button-font-weight: var(--fw-semibold);
  --vaadin-button-gap: var(--space-2);
}
vaadin-button[data-ts-role]:not([disabled]):not([aria-busy="true"]):not([data-ts-cooldown]) { cursor:pointer; }
vaadin-button[data-ts-size="sm"] {
  --vaadin-button-height: var(--control-sm);
  --vaadin-button-padding: 0 var(--space-2);
  --vaadin-button-font-size: var(--fs-xs);
}
vaadin-button[data-ts-role="main"] { --vaadin-button-background: var(--accent); --vaadin-button-text-color: var(--text-on-accent); }
vaadin-button[data-ts-role="main"]:hover { --vaadin-button-background: var(--accent-hover); }
vaadin-button[data-ts-role="neutral"] {
  --vaadin-button-background: var(--surface-card);
  --vaadin-button-text-color: var(--text-primary);
  --vaadin-button-border: 1px solid var(--border-strong);
}
vaadin-button[data-ts-role="neutral"]:hover { --vaadin-button-background: var(--canvas); }
vaadin-button[data-ts-role="destructive"] {
  --vaadin-button-background: var(--danger-bg);
  --vaadin-button-text-color: var(--danger-fg);
  --vaadin-button-border: 1px solid var(--danger-border);
}
vaadin-button[data-ts-role="destructive"]:hover { --vaadin-button-background: #F7D9D6; }
vaadin-button[data-ts-role="link"] { --vaadin-button-background: transparent; --vaadin-button-text-color: var(--accent); }
vaadin-button[data-ts-role="link"]:hover { --vaadin-button-background: var(--info-bg); }
/* Danger: the confirming action of a dangerous dialog, mirroring .ts-btn--danger; pages have no such role. */
vaadin-button[data-ts-role="danger"] { --vaadin-button-background: var(--danger); --vaadin-button-text-color: var(--white); }
vaadin-button[data-ts-role="danger"]:hover { --vaadin-button-background: var(--danger-hover); }
vaadin-button[data-ts-icon-only] { --vaadin-button-padding: 0; padding: 0; width: var(--control-md); }
vaadin-button[data-ts-icon-only][data-ts-size="sm"] { width: var(--control-sm); }
/* Disabled action of any role, mirroring .ts-btn:disabled: Lumo only greys the text, which is unreadable on a filled role. */
vaadin-button[data-ts-role][disabled] {
  --vaadin-button-background: var(--canvas);
  /* Lumo paints the text of a disabled button with this colour, not with --vaadin-button-text-color. */
  --lumo-disabled-text-color: var(--text-tertiary);
  --vaadin-button-border: 1px solid var(--border-default);
}
vaadin-button[data-ts-role="link"][disabled] {
  --vaadin-button-background: transparent;
  --vaadin-button-border: 1px solid transparent;
}
/* Cooldown of an action button: looks disabled, shows the seconds left and a draining bar; the client makes it inert. */
vaadin-button[data-ts-cooldown] {
  --vaadin-button-background: var(--canvas);
  --vaadin-button-text-color: var(--text-tertiary);
  --vaadin-button-border: 1px solid var(--border-default);
  position: relative;
  overflow: hidden;
  padding-inline-end: calc(var(--space-2) * 2 + 1.5em);
}
/* The bar takes over the Lumo hover overlay of the host, so it sets every overlay property it relies on. */
vaadin-button[data-ts-cooldown]::before {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--accent);
  opacity: 1;
  border-radius: 0;
  pointer-events: none;
  transform-origin: left;
  animation: ts-cooldown-drain var(--ts-cooldown-duration) linear forwards;
}
@keyframes ts-cooldown-drain { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { vaadin-button[data-ts-cooldown]::before { animation:none; content:none; } }
/*
 * The countdown sits at the end of the button, inside the room the padding leaves, so a full-width button shows it too.
 * It takes over the Lumo press overlay of the host: transparent, blurred and fading in.
 */
vaadin-button[data-ts-cooldown]::after {
  content: attr(data-ts-cooldown);
  position: absolute;
  inset: 0 var(--space-2) 0 auto;
  display: flex;
  align-items: center;
  border-radius: 0;
  font-family: var(--font-mono);
  opacity: 1;
  background: none;
  filter: none;
  transform: none;
  transition: none;
}
vaadin-button[aria-busy="true"] { cursor: progress; }
vaadin-button > .ts-spinner { display: inline-block; }
/* A column keeps buttons at their own width, like the line does. */
.ts-vstack > vaadin-button { align-self: flex-start; }
/* Guest card: the wide main action of size L; link actions in a label row or the links line read as inline links. */
.ts-guest-card__body > vaadin-button[data-ts-role="main"] {
  --vaadin-button-height: var(--control-lg);
  --vaadin-button-padding: 0 var(--space-4);
  --vaadin-button-font-size: var(--fs-body);
  --vaadin-button-border-radius: var(--radius-lg);
  width: 100%;
}
:is(.ts-field__aside, .ts-guest__links) > vaadin-button[data-ts-role="link"] {
  --vaadin-button-height: auto;
  --vaadin-button-padding: 0;
  --vaadin-button-font-size: var(--fs-sm);
  --vaadin-button-font-weight: var(--fw-medium);
  --vaadin-button-background: transparent;
}
.ts-field__aside > vaadin-button[data-ts-role="link"] { --vaadin-button-font-size: var(--fs-xs); }
:is(.ts-field__aside, .ts-guest__links) > vaadin-button[data-ts-role="link"]:hover { text-decoration: underline; }
/* Guest card: fields of size L and a segmented choice across the card. */
.ts-guest-card :is(vaadin-text-field, vaadin-password-field) {
  --lumo-text-field-size: calc(var(--control-lg) - 2px);
  --vaadin-input-field-value-font-size: var(--fs-body);
}
.ts-guest-card__body > .ts-field__value--inline { display: flex; }
.ts-guest-card__body vaadin-radio-group.ts-seg { flex: 1; }

/* Fields: label, helper and error typography and the shared white bordered input appearance. */
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-date-time-picker, vaadin-integer-field, vaadin-number-field, vaadin-custom-field) {
  --vaadin-input-field-label-font-size: var(--fs-xs);
  --vaadin-input-field-label-font-weight: var(--fw-medium);
  --vaadin-input-field-label-color: var(--text-primary);
  --vaadin-input-field-helper-font-size: var(--fs-caption);
  --vaadin-input-field-helper-color: var(--text-secondary);
  --vaadin-input-field-error-font-size: var(--fs-caption);
  --vaadin-input-field-error-color: var(--danger);
  --vaadin-input-field-value-font-size: var(--fs-sm);
  /* The input-field part draws a 1px border outside this height; keep the whole control at --control-md. */
  --lumo-text-field-size: calc(var(--control-md) - 2px);
}
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field)::part(input-field) {
  background: var(--surface-card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
}
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field)[focused]::part(input-field) {
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field)[invalid]::part(input-field) {
  border-color: var(--danger);
}
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field)[disabled]::part(input-field) {
  background: var(--canvas);
  border-color: var(--border-default);
}
/* Read-only field: the value keeps its type and can be copied; the dashed border tells it apart from an input. */
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field)[readonly]:not([disabled])::part(input-field) {
  background: transparent;
  border-style: dashed;
  border-color: var(--border-strong);
  box-shadow: none;
  /* Lumo greys a read-only value through this part; the value keeps the primary text colour. */
  color: var(--text-primary);
}
/* Inverse read-only controls stop at tables, which own a neutral surface and reuse normal field styling. */
@scope (.ts-block--dark) to (.ts-table) {
  :scope :is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
      vaadin-integer-field, vaadin-number-field)[readonly]:not([disabled])::part(input-field) {
    color: var(--white);
    border-color: var(--ink-600);
  }
  :scope vaadin-custom-field[readonly]:not([disabled]) .ts-lookup { color:var(--white); border-color:var(--ink-600); }
  :scope .ts-progress { background:var(--ink-700); }
  :scope .ts-progress__bar { background:var(--white); }
}
.ts-field__value > :is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-select, vaadin-date-picker, vaadin-time-picker,
    vaadin-date-time-picker, vaadin-integer-field, vaadin-number-field, vaadin-custom-field) {
  width: 100%;
  padding-block: 0;
}
/* Label-less select in a line or a block head: no room for a label above; the small one matches small buttons. */
vaadin-select[data-ts-size] { padding-block: 0; }
/* The frame takes its height from --lumo-text-field-size and the value button inside from --lumo-size-m; the border
   adds 2px. */
vaadin-select[data-ts-size="sm"] {
  --lumo-text-field-size: calc(var(--control-sm) - 2px);
  --lumo-size-m: calc(var(--control-sm) - 2px);
  --vaadin-input-field-value-font-size: var(--fs-xs);
}
/* A compact select keeps its height: the error shows as the red border, and its text stays the accessible description. */
vaadin-select[data-ts-size="sm"]::part(error-message) { display: none; }
.ts-field__value > vaadin-checkbox { display: flex; align-items: center; min-height: var(--control-md); }
/* Native values remain separate from the shadow field frame, clear/toggle buttons, hints and errors. */
:is(vaadin-text-field, vaadin-password-field, vaadin-text-area, vaadin-date-picker, vaadin-time-picker,
    vaadin-integer-field, vaadin-number-field) > :is(input, textarea),
vaadin-select > [slot="value"], .ts-code__area, vaadin-radio-button > label {
  filter:var(--ts-value-filter, none);
}
vaadin-checkbox::part(checkbox), vaadin-radio-button::part(radio), vaadin-switch::part(switch) { filter:var(--ts-value-filter, none); }
vaadin-text-field[data-ts-mono] > input, vaadin-password-field[data-ts-mono] > input, vaadin-integer-field > input, vaadin-number-field > input {
  font-family: var(--font-mono);
}
vaadin-checkbox {
  --vaadin-checkbox-size: 18px;
  --vaadin-checkbox-background: var(--surface-card);
  --vaadin-input-field-border-width: 1.5px;
  --vaadin-input-field-border-color: var(--ink-300);
  --vaadin-checkbox-checkmark-color: var(--white);
}
vaadin-checkbox[checked] { --vaadin-input-field-border-color: var(--accent); }
vaadin-checkbox[invalid] { --vaadin-input-field-border-color: var(--danger); }
vaadin-checkbox[disabled] { --vaadin-input-field-border-color: var(--border-default); }
vaadin-checkbox[readonly]:not([disabled]) {
  --vaadin-checkbox-background: transparent;
  --vaadin-input-field-border-color: var(--border-strong);
}

/* Table selection: the row checkbox sits on the middle line of its cell. */
.ts-table vaadin-checkbox { vertical-align: middle; }

/* Date range: two pickers side by side inside one field. */
.ts-date-range { display: flex; align-items: center; gap: var(--space-2); }
.ts-date-range > vaadin-date-picker { flex: 1; min-width: 0; padding-block: 0; }
.ts-date-range__prefix { flex:none; margin-inline-end:var(--space-1); color:var(--text-secondary); font:inherit; white-space:nowrap; }
.ts-field__value vaadin-date-time-picker > :is([slot="date-picker"], [slot="time-picker"]) { padding-block: 0; }

/* Lookup: a bordered field box holding the value button and the clear and open actions. */
.ts-lookup {
  display: flex; align-items: center; gap: var(--space-2); height: var(--control-md); box-sizing: border-box;
  padding: 0 var(--space-1) 0 var(--space-3); border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  background: var(--surface-card); cursor: pointer;
}
.ts-lookup__text {
  flex: 1; min-width: 0; padding: 0; border: 0; background: none; outline: none;
  /* The field host sets a tall line height; the value keeps the text line of the other fields. */
  font: inherit; font-size: var(--fs-sm); line-height: var(--lh-sm); color: inherit; text-align: left; cursor: inherit;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ts-lookup:has(.ts-lookup__text:focus-visible) { border-color: var(--border-focus); box-shadow: 0 0 0 3px var(--accent-ring); }
vaadin-custom-field[invalid] .ts-lookup { border-color: var(--danger); }
vaadin-custom-field[readonly]:not([disabled]) .ts-lookup { background: transparent; border-style: dashed; cursor: default; }
vaadin-custom-field[disabled] .ts-lookup {
  background: var(--canvas); border-color: var(--border-default); color: var(--text-disabled); cursor: default;
}
.ts-lookup-search { padding-top: 0; margin-bottom: var(--space-3); }
/* Multi-value lookup: .ts-chip values as in MultiSelect; the value button stays first in the DOM, as the input the label
   focuses, and the chips are shown before it. The pager goes under the table, the footer holds the count and the actions. */
.ts-lookup--many { height: auto; min-height: var(--control-md); padding-block: 3px; }
.ts-lookup--many:has(.ts-chip) { padding-left: 6px; }
.ts-lookup__chips { order: -1; display: flex; flex-wrap: wrap; gap: var(--space-1); min-width: 0; }
.ts-lookup__chips .ts-chip { white-space: nowrap; }
vaadin-custom-field[disabled] .ts-lookup__chips .ts-chip { background: var(--muted); color: var(--text-disabled); }
.ts-lookup-pager { margin-top: var(--space-3); }
.ts-lookup-count { flex: 1; font-size: var(--fs-sm); }

/* Toast: the notification card is only a positioner, the .ts-toast markup draws the card. */
vaadin-notification-card[theme~="ts-toast"]::part(overlay) { background: none; box-shadow: none; padding: 0; }
vaadin-notification-card[theme~="ts-toast"]::part(content) { padding: 0; }

/* Dialog: the rounded overlay carries the shadow outside scrollable content; .ts-dialog draws the card. */
vaadin-dialog[theme~="ts-dialog"]::part(backdrop) { background:var(--overlay); }
vaadin-dialog[theme~="ts-dialog"]::part(overlay) { background: none; box-shadow: var(--shadow-dialog); border-radius: var(--radius-2xl); overflow: hidden; }
vaadin-dialog[theme~="ts-dialog"]::part(content) { padding: 0; border-radius: inherit; }
vaadin-dialog[theme~="ts-dialog"] .ts-dialog { box-shadow: none; }
/* The overlay takes the width of the card, so the card limits itself by the viewport rather than its parent. */
vaadin-dialog .ts-dialog { max-width: calc(100vw - 32px); }
/* Tables in a dialog body keep the primary text colour of a table, not the secondary one of dialog text. */
.ts-dialog__stack { display: flex; flex-direction: column; gap: 6px; }
.ts-dialog--alert .ts-dialog__title { color: var(--text-primary); }

/* Action menu: vaadin-context-menu styled as the .ts-menu popover of the shared styling; the items carry .ts-menu__item. */
vaadin-context-menu[theme~="ts-menu"]::part(overlay) {
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-popover);
}
vaadin-context-menu[theme~="ts-menu"]::part(content) { padding: 6px; min-width: 220px; }
vaadin-context-menu-item.ts-menu__item {
  min-height: 28px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  font: var(--fw-medium) var(--fs-sm) var(--font-sans);
  color: var(--text-primary);
}
vaadin-context-menu-item.ts-menu__item:hover,
vaadin-context-menu-item.ts-menu__item[focus-ring] { background: var(--canvas); }
vaadin-context-menu-item.ts-menu__item--danger { color: var(--danger); }
vaadin-context-menu-item.ts-menu__item[disabled] { color: var(--text-tertiary); cursor: default; }
vaadin-context-menu-list-box hr { height: 1px; margin: 4px 0; border: 0; background: var(--line-subtle); }

/* Radio groups and switches use Vaadin state and focus with the canonical control geometry. */
vaadin-radio-group[data-ts-input], vaadin-switch[data-ts-input] { padding-block:0; }
vaadin-radio-group.ts-radio-group::part(group-field) { display:flex; flex-wrap:wrap; gap:var(--space-3); }
vaadin-radio-button {
  --vaadin-radio-button-size:18px;
  --vaadin-radio-button-dot-size:8px;
  --vaadin-radio-button-background:var(--surface-card);
  --vaadin-radio-button-background-hover:var(--surface-card);
  --vaadin-radio-button-dot-color:var(--accent);
  --vaadin-radio-button-disabled-background:var(--muted);
  --vaadin-radio-button-disabled-dot-color:var(--text-tertiary);
  --vaadin-radio-button-label-color:var(--text-primary);
  --vaadin-radio-button-label-font-size:var(--fs-sm);
  margin:0;
}
vaadin-radio-button::part(radio) { border:1.5px solid var(--ink-300); box-sizing:border-box; }
vaadin-radio-button[checked]::part(radio) { border-color:var(--accent); }
vaadin-radio-button[focus-ring]::part(radio) { outline:1px solid var(--border-focus); outline-offset:0; box-shadow:0 0 0 3px var(--accent-ring); }
vaadin-radio-button[disabled]::part(radio), vaadin-radio-button[disabled] > label { opacity:1; }
.ts-choice-label { display:inline-flex; align-items:center; gap:10px; }
vaadin-radio-group.ts-seg { padding:0; background:none; border-radius:0; }
vaadin-radio-group.ts-seg::part(group-field) { display:flex; gap:2px; padding:3px; border-radius:var(--radius-lg); background:var(--muted); }
vaadin-radio-group.ts-seg > vaadin-radio-button {
  position:relative; display:flex; flex:1; align-items:center; justify-content:center; height:26px; padding:0 var(--space-3);
  border-radius:7px; color:var(--text-secondary); font:var(--fw-semibold) var(--fs-xs) var(--font-sans);
  white-space:nowrap; cursor:pointer;
  --vaadin-radio-button-label-padding:0;
  --vaadin-radio-button-label-color:inherit;
  --vaadin-radio-button-label-font-size:inherit;
  transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
/* The label only toggles the choice, so its click area and the segment cursor cover the whole segment. */
vaadin-radio-group.ts-seg > vaadin-radio-button > label { cursor:inherit; }
vaadin-radio-group.ts-seg > vaadin-radio-button > label::after { content:""; position:absolute; inset:0; }
/* Keep the native radio input focusable while hiding its marker in segmented controls. */
vaadin-radio-group.ts-seg > vaadin-radio-button::part(radio) { position:absolute; width:1px; height:1px; padding:0; border:0; overflow:hidden; clip-path:inset(50%); }
vaadin-radio-group.ts-seg > vaadin-radio-button[checked] { background:var(--surface-card); color:var(--text-primary); box-shadow:var(--shadow-segment); }
vaadin-radio-group.ts-seg > vaadin-radio-button[focus-ring] { outline:1px solid var(--border-focus); outline-offset:0; box-shadow:0 0 0 3px var(--accent-ring); }
vaadin-radio-group.ts-seg--sm > vaadin-radio-button { height:22px; padding:0 10px; font-size:var(--fs-caption); }
vaadin-radio-group[readonly]::part(group-field) { background:transparent; border:1px dashed var(--border-strong); border-radius:var(--radius-md); }
vaadin-radio-group[readonly] > vaadin-radio-button { cursor:default; }
vaadin-radio-group[readonly]:not([disabled]) > vaadin-radio-button > label { color:inherit; }
vaadin-radio-group.ts-seg[disabled]::part(group-field) { background:var(--muted); color:var(--text-tertiary); border-color:var(--border-default); }
vaadin-radio-group[disabled] > vaadin-radio-button { color:var(--text-tertiary); cursor:default; }
vaadin-radio-group[disabled] > vaadin-radio-button > label { color:var(--text-tertiary); }
vaadin-switch[data-ts-input] {
  --vaadin-switch-width:36px;
  --vaadin-switch-height:20px;
  --vaadin-switch-background:var(--line-strong);
  --vaadin-switch-border-width:0;
  --vaadin-switch-border-radius:var(--radius-pill);
  --vaadin-switch-marker-width:16px;
  --vaadin-switch-marker-height:16px;
  --vaadin-switch-marker-color:var(--white);
  --vaadin-switch-marker-border-width:0;
  --vaadin-switch-marker-border-radius:50%;
  --vaadin-switch-marker-scale:1;
}
vaadin-switch[checked] { --vaadin-switch-background:var(--accent); }
vaadin-switch[focus-ring]::part(switch) { outline:1px solid var(--border-focus); outline-offset:0; box-shadow:0 0 0 3px var(--accent-ring); }
vaadin-switch[disabled]::part(switch) { background:var(--muted); opacity:1; }
vaadin-switch[readonly]:not([disabled])::part(switch) { background:var(--border-strong); }
vaadin-switch[readonly][checked]:not([disabled])::part(switch) { background:var(--accent); }

/* The line gutter follows the actual textarea scroll inside Vaadin. */
.ts-code__lines { overflow:hidden; max-height:100%; flex:none; }
textarea.ts-code__area { margin:0; min-width:0; width:100%; min-height:0; height:100%; resize:none; box-sizing:border-box; white-space:pre; overflow-wrap:normal; overflow-x:auto; }
.ts-multiselect__clear { flex:none; width:auto; border:0; border-radius:var(--radius-xs); padding:0 var(--space-1); background:transparent; color:inherit; font:inherit; font-size:var(--fs-sm); line-height:var(--lh-sm); white-space:nowrap; cursor:pointer; }
.ts-multiselect__clear:hover { background:var(--canvas); }
vaadin-custom-field[readonly] .ts-code { outline:1px dashed var(--border-strong); }
vaadin-custom-field[disabled] .ts-code { background:var(--muted); color:var(--text-tertiary); }
vaadin-custom-field[disabled] .ts-code__area, vaadin-custom-field[disabled] .ts-code__lines { color:var(--text-tertiary); }

/* Vaadin positions the popup; the shared styling provides its surface and content. */
vaadin-popover[theme~="ts-popover"]::part(overlay) { background:var(--surface-card); border:1px solid var(--border-default); border-radius:var(--radius-xl); box-shadow:var(--shadow-popover); min-width:260px; overflow:hidden; }
vaadin-popover[theme~="ts-popover"]::part(content) { padding:0; border-radius:inherit; background:var(--surface-card); }
vaadin-popover .ts-pop { padding:var(--space-4); border-radius:inherit; background:transparent; }
testsys-date-range-calendar { display:block; padding:var(--space-4); box-sizing:border-box; }
vaadin-popover .ts-popover__search { width:100%; box-sizing:border-box; }
vaadin-popover .ts-options { min-width:300px; }
vaadin-popover .ts-popover__foot { white-space:nowrap; }
vaadin-popover .ts-popover__foot > span { flex:1; }

/* Drawer is a modal Flow Dialog placed at the viewport edge. */
vaadin-dialog[theme~="ts-drawer"]::part(backdrop) { background:var(--overlay-drawer); }
/* The overlay host lays out the panel; a zero inset and an auto left margin pin it to the right edge. */
vaadin-dialog[theme~="ts-drawer"] { --vaadin-overlay-viewport-inset:0px; }
vaadin-dialog[theme~="ts-drawer"]::part(overlay) { animation:ts-drawer-in var(--dur-slow) var(--ease-out); width:480px; max-width:100vw; height:100%; max-height:100%; margin:0 0 0 auto; background:var(--surface-card); border-radius:var(--radius-xl); overflow:hidden; box-shadow:var(--shadow-drawer); }
vaadin-dialog[theme~="ts-drawer"]::part(content) { height:100%; border-radius:inherit; overflow:hidden; }
vaadin-dialog[theme~="ts-drawer"] .ts-dialog { animation:none; width:480px; max-width:100vw; height:100%; max-height:100%; display:flex; flex-direction:column; border-radius:var(--radius-xl); overflow:hidden; }
vaadin-dialog[theme~="ts-drawer"] .ts-dialog__body { flex:1; overflow:auto; }
vaadin-dialog[theme~="ts-drawer"] .ts-dialog__foot { border-radius:0; }
vaadin-tooltip::part(overlay) { background:var(--ink-900); color:var(--white); font:var(--fw-medium) var(--fs-caption)/18px var(--font-sans); border-radius:var(--radius-sm); padding:6px 10px; max-width:240px; }

/* Upload keeps the browser's native transport and file-list accessibility. */
vaadin-upload.ts-drop { width:100%; box-sizing:border-box; }
vaadin-upload.ts-drop::part(primary-buttons) { flex-wrap:wrap; gap:var(--space-2); }
vaadin-upload.ts-drop::part(drop-label) { font:var(--fw-regular) var(--fs-xs)/var(--lh-xs) var(--font-sans); }
vaadin-upload.ts-drop > vaadin-upload-file-list[slot="file-list"]:not(:has(vaadin-upload-file)) { display:none; }
vaadin-upload.ts-drop[dragover] { border-color:var(--accent); background:var(--accent-softer); }
vaadin-upload.ts-drop[disabled] { cursor:default; background:var(--canvas); color:var(--text-disabled); }
vaadin-upload-file::part(name) { font:var(--fw-semibold) var(--fs-sm) var(--font-sans); filter:var(--ts-value-filter, none); }
vaadin-upload-file::part(status) { color:var(--text-secondary); }
.ts-filedrop { display:flex; flex-direction:column; gap:var(--space-2); min-width:0; }
.ts-filedrop > span:first-child { font:var(--fw-semibold) var(--fs-sm) var(--font-sans); }
.ts-filedrop__meta { display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2); font:var(--fw-regular) var(--fs-xs) var(--font-sans); }
.ts-filedrop__status:empty, .ts-filedrop__actions:empty { display:none; }
.ts-date-range { gap:var(--space-2); }
.ts-date-range > button { flex:none; }

vaadin-date-picker[data-ts-range-part]::part(toggle-button) { display:none; }

vaadin-custom-field[invalid] .ts-code { outline:1px solid var(--danger); }

/* Header overlays keep every Vaadin background within the same rounded boundary. */
vaadin-popover[theme~="ts-header-popup"]::part(overlay) { border:1px solid var(--border-default); border-radius:var(--radius-xl); background:var(--surface-card); box-shadow:var(--shadow-popover); overflow:hidden; max-width:calc(100vw - 24px); }
vaadin-popover[theme~="ts-header-popup"]::part(content) { padding:0; border-radius:inherit; background:var(--surface-card); overflow:auto; }
vaadin-popover[theme~="ts-header-notifications-popup"]::part(overlay) { width:360px; }
vaadin-popover[theme~="ts-header-mega"] { --vaadin-popover-offset-top:0px; }
vaadin-popover[theme~="ts-header-mega"]::part(overlay) { width:min(960px,calc(100vw - 24px)); max-height:calc(100vh - 70px); }
vaadin-popover[theme~="ts-header-popup"]::part(overlay) { animation:ts-pop-in var(--dur-base) var(--ease-out); }
@media (prefers-reduced-motion: reduce) { vaadin-popover[theme~="ts-header-popup"]::part(overlay) { animation:none; } }

/* Only header arrival cards occupy the space below the header; ordinary toasts retain their native position. */
vaadin-notification-card[theme~="ts-header-arrival"] { position:fixed; top:calc(var(--header-height) + var(--space-3)); right:var(--space-6); margin:0; max-width:calc(100vw - 2 * var(--space-6)); }
vaadin-notification-card[theme~="ts-header-arrival"]::part(overlay) { border-radius:var(--radius-xl); overflow:hidden; }

/* The menu-search mode sizes the existing popup to its visible groups. */
vaadin-popover[theme~="ts-header-menu-search"]::part(overlay) { width:min(calc(var(--ts-menu-columns,4) * var(--col-wide) + 2 * var(--space-3) + (var(--ts-menu-columns,4) - 1) * var(--space-3)),calc(100vw - 24px)); min-width:0; }

@media (prefers-reduced-motion: reduce) { vaadin-dialog[theme~="ts-drawer"]::part(overlay) { animation:none; } }

.ts-field__value > .ts-filedrop {
    min-width: 0;
    width: 100%;
}

.ts-drawer-table {
    grid-column: 1 / -1;
    min-width: 0;
}

.ts-drawer-table > .ts-block__title {
    display: block;
    margin-bottom: 8px;
}
