@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700;800&display=swap");

/* =========================================================
   Würth UI — the shared stylesheet.
   Every colour, shadow, space, radius and size comes from tokens.css.
   Light and dark come from the theme on <html data-theme>.
   ========================================================= */

/* ── Base ─────────────────────────────────────────────────────── */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.5;
}

button,
input,
select,
textarea {
    font: inherit;
    color: inherit;
}

h1, h2, h3 {
    text-wrap: balance;
}

/* Tabler Icons: 2-unit strokes on a 24-unit grid, in the colour of the text */
.wh-icon {
    flex: none;
    width: var(--wh-icon);
    height: var(--wh-icon);
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vertical-align: -0.125em;
}

.wh-icon.is-filled {
    fill: currentColor;
    stroke: none;
}

.wh-tabular {
    font-variant-numeric: tabular-nums;
}

/* The Würth logo. In dark the black wordmark turns white and the red stays: the negative logo */
.wh-logo {
    display: block;
    flex: none;
    max-width: none;
    width: auto;
    height: 26px;
}

[data-theme="dark"] .wh-logo {
    filter: url(#wh-logo-negative);
}

.wh-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}


/* ── Sizes: every control reads its height, text and padding from here ── */
/* --wh-h height · --wh-icon icon size · --wh-fs/--wh-lh text · --wh-px button side padding
   --wh-fx field side padding · --wh-r corner · --wh-label-fs field label */

:root,
.wh-size-40 {
    --wh-h: var(--control-40);
    --wh-icon: var(--icon);
    --wh-fs: 16px;
    --wh-lh: 24px;
    --wh-px: 16px;
    --wh-fx: 16px;
    --wh-r: var(--radius-md);
    --wh-label-fs: 14px;
    --wh-label-lh: 20px;
}

:root {
    --wh-gap: var(--space);
    --wh-gap-tight: var(--space-tight);
    --wh-r-lg: var(--radius-lg);
}

.wh-revit {
    --wh-gap: var(--space-revit);
    --wh-gap-tight: var(--space-revit-tight);
    --wh-r-lg: var(--radius-md);
    --wh-h: var(--control-28);
    --wh-icon: var(--icon-sm);
    --wh-fs: 13px;
    --wh-lh: 18px;
    --wh-px: 10px;
    --wh-fx: 8px;
    --wh-r: var(--radius-sm);
    --wh-label-fs: 12px;
    --wh-label-lh: 16px;
    font-size: 13px;
    line-height: 18px;
}

.wh-size-32 {
    --wh-h: var(--control-32);
    --wh-icon: var(--icon);
    --wh-fs: 14px;
    --wh-lh: 20px;
    --wh-px: 16px;
    --wh-fx: 8px;
    --wh-r: var(--radius-md);
    --wh-label-fs: 14px;
    --wh-label-lh: 20px;
}

.wh-size-28 {
    --wh-h: var(--control-28);
    --wh-icon: var(--icon-sm);
    --wh-fs: 13px;
    --wh-lh: 18px;
    --wh-px: 10px;
    --wh-fx: 8px;
    --wh-r: var(--radius-sm);
    --wh-label-fs: 12px;
    --wh-label-lh: 16px;
}

.wh-size-24 {
    --wh-h: var(--control-24);
    --wh-icon: var(--icon-sm);
    --wh-fs: 12px;
    --wh-lh: 16px;
    --wh-px: 8px;
    --wh-fx: 6px;
    --wh-r: var(--radius-sm);
    --wh-label-fs: 12px;
    --wh-label-lh: 16px;
}


/* ── Layout helpers ───────────────────────────────────────────── */

.wh-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--wh-gap-tight);
}

.wh-stack {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--wh-gap);
    align-content: start;
}


/* ── Stacking order ───────────────────────────────────────────
   The page overlay bar 1075 · the dialog scrim 1078 · menus and calendars (on the body) 1080 ·
   tooltips 1100. Menus opened from a dialog sit above its scrim. */

/* ── Room for the focus halo ──────────────────────────────────── */
/* The halo sits 4 px outside a control. Anything that clips its content (a scroll area, a table
   wrapper) keeps 4 px of room inside its edge without moving its content: add wh-ring-room. */

.wh-ring-room {
    padding: 4px;
    margin: -4px;
}


/* ── Overlay scrollbars: no gutter, nothing shifts when a bar appears ── */

html,
.wh-scroll {
    scrollbar-width: none;
}

html::-webkit-scrollbar,
.wh-scroll::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.wh-scroll {
    position: relative;
}

.wh-bar-track {
    position: absolute;
    z-index: 26;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-open) var(--ease);
}

.wh-bar-track.is-page {
    position: fixed;
    z-index: 1075;
}

.wh-bar-track.is-v {
    width: 12px;
}

.wh-bar-track.is-h {
    height: 12px;
}

.wh-bar-track.is-visible {
    opacity: 1;
    pointer-events: auto;
}

.wh-bar-thumb {
    position: absolute;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--ink) 35%, transparent);
    transition: width var(--duration-fast) var(--ease), height var(--duration-fast) var(--ease), background-color var(--duration-fast) var(--ease), right var(--duration-fast) var(--ease), bottom var(--duration-fast) var(--ease);
}

.is-v > .wh-bar-thumb {
    right: 3px;
    width: 6px;
}

.is-h > .wh-bar-thumb {
    bottom: 3px;
    height: 6px;
}

.wh-bar-track:hover > .wh-bar-thumb,
.wh-bar-thumb.is-dragging {
    background: color-mix(in srgb, var(--ink) 55%, transparent);
}

.is-v:hover > .wh-bar-thumb,
.is-v > .wh-bar-thumb.is-dragging {
    right: 1px;
    width: 10px;
}

.is-h:hover > .wh-bar-thumb,
.is-h > .wh-bar-thumb.is-dragging {
    bottom: 1px;
    height: 10px;
}

body.is-dragging-bar {
    user-select: none;
}

/* A soft fade on the edge that has more to scroll to (the mask only sets transparency) */
.wh-scroll.is-more-right {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
}

.wh-scroll.is-more-left {
    -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent);
}

.wh-scroll.is-more-left.is-more-right {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
}


/* ── Spec sheets: the annotated state matrices on these pages ──── */

.wh-spec {
    padding: 8px 16px 16px;
    color: var(--ink);
}

.wh-spec + .wh-spec {
    padding-top: 0;
}

.wh-spec-scroll {
    overflow-x: auto;
    padding: 8px 0 8px;
}

.wh-spec-grid {
    display: grid;
    width: max-content;
    position: relative;
}

.wh-spec-col,
.wh-spec-row {
    color: var(--spec);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 400;
    line-height: 16px;
    white-space: nowrap;
}

.wh-spec-col {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    gap: 2px;
    padding: 6px 4px 0;
    text-align: center;
}

.wh-spec-col > .wh-spec-bracket {
    position: relative;
    align-self: stretch;
    height: 7px;
    margin-top: 5px;
    border: 1px solid var(--spec);
    border-bottom: 0;
    border-radius: 4px 4px 0 0;
}

.wh-spec-col > .wh-spec-bracket::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -5px;
    width: 1px;
    height: 4px;
    background: var(--spec);
}

.wh-spec-row {
    display: flex;
    justify-content: flex-end;
    align-items: stretch;
    gap: 10px;
    padding: 2px 10px 2px 0;
}

.wh-spec-row > .wh-spec-text {
    align-self: center;
    text-align: right;
}

.wh-spec-row > .wh-spec-bracket {
    position: relative;
    flex: none;
    width: 7px;
    margin: 4px 0;
    border: 1px solid var(--spec);
    border-right: 0;
    border-radius: 4px 0 0 4px;
}

.wh-spec-row > .wh-spec-bracket::before {
    content: "";
    position: absolute;
    top: 50%;
    left: -6px;
    width: 5px;
    height: 1px;
    background: var(--spec);
}

.wh-spec-note {
    font-size: 11px;
    line-height: 14px;
}

.wh-spec-frame {
    border: 1px dashed var(--spec);
    border-radius: 2px;
    pointer-events: none;
}

.wh-spec-cell {
    position: relative;
    display: flex;
    align-items: center;
    padding: 14px 12px;
    min-width: 0;
}

.wh-spec-cell.is-center {
    justify-content: center;
}

.wh-spec-cell.is-top {
    align-items: flex-start;
}

.wh-spec-empty {
    color: var(--spec);
    font-size: 12px;
}


/* ── Motion off when asked ────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition: none !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
    }
}


/* ── Button ───────────────────────────────────────────────────── */
/* States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus,
   :disabled / .is-disabled, .is-busy. The .is-* classes force a state on the spec sheets. */

.wh-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--wh-gap-tight);
    height: var(--wh-h);
    padding: 0 var(--wh-px);
    border: 1px solid transparent;
    border-radius: var(--wh-r);
    background: transparent;
    font-family: var(--font-sans);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    font-weight: 400;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: color var(--duration-fast) var(--ease), background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

/* With an icon: the label at the left padding, the icon at the right; sides = the space above the icon + 4 px */
.wh-btn:has(> .wh-icon),
.wh-btn:has(> .wh-spinner) {
    justify-content: space-between;
    gap: var(--wh-gap);
    padding: 0 calc((var(--wh-h) - var(--wh-icon)) / 2 + 4px);
    text-align: left;
}

.wh-btn > .wh-icon,
.wh-btn > .wh-spinner {
    order: 2;
}

/* Nothing escapes a button: the label shrinks and ends in an ellipsis, the icon keeps its size */
.wh-btn {
    min-width: 0;
    max-width: 100%;
}

.wh-btn > .wh-btn-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Phones: buttons in a bar or toolbar fill the row, sharing it when their labels fit */
@media (max-width: 575.98px) {
    .wh-bar {
        flex-wrap: wrap;
    }

    .wh-bar > .wh-btn,
    .wh-bar > * > .wh-btn {
        flex: 1 1 var(--button-min);
    }
}

.wh-btn:focus-visible,
.wh-btn.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

.wh-btn:disabled,
.wh-btn.is-disabled {
    opacity: 0.55;
    cursor: default;
}

.wh-btn.is-busy {
    pointer-events: none;
}

/* Primary: one per screen */
.wh-btn-primary {
    border-color: var(--red);
    background: var(--red);
    color: var(--on-red);
}

.wh-btn-primary:hover:not(:disabled):not(.is-disabled),
.wh-btn-primary.is-hover {
    border-color: var(--red-hover);
    background: var(--red-hover);
}

.wh-btn-primary:active:not(:disabled):not(.is-disabled),
.wh-btn-primary.is-active {
    border-color: var(--red-press);
    background: var(--red-press);
}

/* Standard: every other button */
.wh-btn-standard {
    border-color: var(--edge);
    background: var(--control);
    color: var(--ink);
}

.wh-btn-standard:hover:not(:disabled):not(.is-disabled),
.wh-btn-standard.is-hover {
    border-color: var(--edge-hover);
    background: var(--hover);
}

.wh-btn-standard:active:not(:disabled):not(.is-disabled),
.wh-btn-standard.is-active,
.wh-btn-standard[aria-pressed="true"] {
    border-color: var(--edge-hover);
    background: var(--press);
}

.wh-btn-standard:focus-visible,
.wh-btn-standard.is-focus {
    border-color: var(--edge-hover);
}

/* Red outline: the one secondary emphasis */
.wh-btn-outline {
    border-color: var(--red-line);
    background: transparent;
    color: var(--red-text);
}

.wh-btn-outline:hover:not(:disabled):not(.is-disabled),
.wh-btn-outline.is-hover {
    border-color: var(--red-text);
}

.wh-btn-outline:active:not(:disabled):not(.is-disabled),
.wh-btn-outline.is-active {
    border-color: var(--red-text);
    background: var(--hover);
}

/* Revit buttons sit one size above their fields: 32 px, and 28 px where the fields are 24 px */
.wh-revit .wh-btn {
    --wh-h: var(--control-32);
    --wh-icon: var(--icon);
    --wh-px: 12px;
}

.wh-revit .wh-size-24 .wh-btn,
.wh-revit .wh-btn.wh-size-24 {
    --wh-h: var(--control-28);
    --wh-icon: var(--icon-sm);
    --wh-px: 10px;
}

/* The one big Revit button: the Varifix panel's full-width primary at the bottom, 36 px at 14 px */
.wh-revit .wh-size-40 .wh-btn,
.wh-revit .wh-btn.wh-size-40 {
    --wh-h: calc(var(--control-32) + var(--space-hair));
    --wh-icon: var(--icon);
    --wh-fs: 14px;
    --wh-lh: 20px;
    --wh-px: 16px;
}

/* Buttons in one bar share one minimum width */
.wh-bar .wh-btn {
    min-width: var(--button-min);
}

/* Icon button: a plain grey icon, a grey square on hover; 32 px on the web */
.wh-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: min(var(--wh-h), var(--control-32));
    height: min(var(--wh-h), var(--control-32));
    padding: 0;
    border: 0;
    border-radius: var(--wh-r);
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease), background-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-icon-btn:hover:not(:disabled):not(.is-disabled),
.wh-icon-btn.is-hover {
    background: var(--press);
    color: var(--ink);
}

.wh-icon-btn:active:not(:disabled):not(.is-disabled),
.wh-icon-btn.is-active {
    background: var(--press-deep);
    color: var(--ink);
}

.wh-icon-btn:focus-visible,
.wh-icon-btn.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

.wh-icon-btn:disabled,
.wh-icon-btn.is-disabled {
    opacity: 0.55;
    cursor: default;
}

/* Spinner: takes the icon's place while the button's job runs */
.wh-spinner {
    display: inline-block;
    flex: none;
    width: var(--wh-icon);
    height: var(--wh-icon);
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: wh-spin 0.75s linear infinite;
}

@keyframes wh-spin {
    to { transform: rotate(360deg); }
}

/* Text link: Reset and other in-line actions */
.wh-link {
    display: inline;
    padding: 0;
    border: 0;
    border-radius: 2px;
    background: none;
    color: var(--red-text);
    font-family: var(--font-sans);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    text-decoration: none;
    cursor: pointer;
}

.wh-link:hover,
.wh-link.is-hover {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.wh-link:focus-visible,
.wh-link.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

/* Revit: buttons in a row are 8 px apart, like the web; other neighbouring controls keep 5 px */
.wh-revit .wh-bar,
.wh-revit .wh-actionbar,
.wh-revit .wh-actionbar-end,
.wh-revit .wh-dialog-foot {
    gap: var(--space-tight);
}

/* Revit bars and dialog footers share the narrower Revit minimum width */
.wh-revit .wh-bar .wh-btn,
.wh-revit .wh-dialog-foot .wh-btn {
    min-width: var(--button-min-revit);
}


/* ── Field: label, box, unit, error ───────────────────────────── */
/* The one field box. Dropdowns, date fields and slider values share its look.
   States: :hover / .is-hover, :focus-within / .is-focus, .is-invalid, .is-disabled. */

.wh-form-field {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.wh-label {
    display: block;
    margin: 0 0 var(--wh-gap-tight);
    color: var(--muted);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 600;
}

.wh-label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--wh-gap);
    margin-bottom: var(--wh-gap-tight);
}

.wh-label-row > .wh-label {
    margin: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-field {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    height: var(--wh-h);
    min-width: 0;
    padding: 0 var(--wh-fx);
    border: 1px solid var(--edge);
    border-radius: var(--wh-r);
    background: var(--control);
    color: var(--ink);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    cursor: text;
    transition: border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-field:hover,
.wh-field.is-hover {
    border-color: var(--edge-hover);
}

.wh-field:focus-within,
.wh-field.is-focus {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-field > input {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: inherit;
    font: inherit;
}

.wh-field > input::placeholder {
    color: var(--muted);
    opacity: 1;
}

.wh-field.is-number > input {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.wh-field > .wh-icon {
    color: var(--muted);
}

.wh-unit {
    flex: none;
    color: var(--unit);
}

.wh-field.is-invalid,
.wh-field.is-invalid:hover,
.wh-field.is-invalid:focus-within {
    border-color: var(--red-text);
}

.wh-field.is-disabled,
.wh-field.is-disabled:hover {
    border-color: var(--edge);
    background: var(--disabled);
    color: var(--muted);
    cursor: default;
}

.wh-field.is-disabled > input {
    cursor: default;
}

/* Read-only: the value as plain text, no box, on the field's line */
.wh-readonly {
    display: flex;
    align-items: center;
    gap: 0.25em;
    min-height: var(--wh-h);
    min-width: 0;
    color: var(--ink);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
}

.wh-readonly.is-number {
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}

.wh-error {
    margin: var(--wh-gap-tight) 0 0;
    color: var(--red-text);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
}

input[type=number] {
    appearance: textfield;
    -moz-appearance: textfield;
}

input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Search: the icon first, a clear button once there is text */
.wh-field.is-search > .wh-icon:first-child {
    order: -1;
}

.wh-field-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: calc(var(--wh-h) - 12px);
    height: calc(var(--wh-h) - 12px);
    margin-right: calc(var(--wh-fx) * -1 + 4px);
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--muted);
    cursor: pointer;
}

.wh-field-clear:hover {
    background: var(--press);
    color: var(--ink);
}


/* ── Checkbox and radio ───────────────────────────────────────── */
/* A 16 px box drawn in CSS: off = control fill with an edge-hover border; on = red fill with an
   on-red tick, dash or dot. The label text follows the size (16, 14, 13, 12 px).
   States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus, :disabled,
   :checked / .is-checked, :indeterminate / .is-indeterminate, .is-invalid.
   The colours run through --wh-mark-* so hover, press and error never fight the on state. */

.wh-checkbox,
.wh-radio {
    --wh-mark-edge: var(--edge-hover);
    --wh-mark-fill: var(--control);
    --wh-mark-on: var(--red);
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex: none;
    width: var(--icon);
    height: var(--icon);
    margin: 0;
    border: 1px solid var(--wh-mark-invalid, var(--wh-mark-edge));
    background: var(--wh-mark-fill);
    vertical-align: middle;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-checkbox {
    border-radius: var(--radius-sm);
}

.wh-radio {
    border-radius: 50%;
}

/* The tick, the dash and the dot. The tick and the dash are the icon set's check and minus, which
   20-choice.js turns into --wh-mark-check and --wh-mark-dash from W.icons when the page loads (and
   marks <html> wh-has-marks), so the marks follow the icon set with no path written here. */
.wh-checkbox::before,
.wh-radio::before {
    content: "";
    position: absolute;
    inset: -1px;
    background: var(--on-red);
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease);
}

.wh-checkbox::before {
    background: transparent;
    -webkit-mask: var(--wh-mark-check) center / var(--icon) var(--icon) no-repeat;
    mask: var(--wh-mark-check) center / var(--icon) var(--icon) no-repeat;
}

.wh-has-marks .wh-checkbox::before {
    background: var(--on-red);
}

.wh-checkbox:indeterminate::before,
.wh-checkbox.is-indeterminate::before {
    -webkit-mask-image: var(--wh-mark-dash);
    mask-image: var(--wh-mark-dash);
}

.wh-radio::before {
    inset: var(--space-hair);
    border-radius: 50%;
}

/* Hover: one shade darker */
.wh-checkbox:enabled:hover,
.wh-radio:enabled:hover,
.wh-check:hover > :is(.wh-checkbox, .wh-radio):enabled,
.wh-tile:hover > .wh-radio:enabled,
.wh-checkbox.is-hover,
.wh-radio.is-hover,
.wh-check.is-hover > :is(.wh-checkbox, .wh-radio),
.wh-tile.is-hover > .wh-radio {
    --wh-mark-edge: var(--muted);
    --wh-mark-fill: var(--hover);
    --wh-mark-on: var(--red-hover);
}

/* Pressed: two shades darker */
.wh-checkbox:enabled:active,
.wh-radio:enabled:active,
.wh-check:active > :is(.wh-checkbox, .wh-radio):enabled,
.wh-tile:active > .wh-radio:enabled,
.wh-checkbox.is-active,
.wh-radio.is-active,
.wh-check.is-active > :is(.wh-checkbox, .wh-radio),
.wh-tile.is-active > .wh-radio {
    --wh-mark-edge: var(--muted);
    --wh-mark-fill: var(--press-deep);
    --wh-mark-on: var(--red-press);
}

/* On: red fill, on-red mark */
.wh-checkbox:checked,
.wh-checkbox:indeterminate,
.wh-checkbox.is-checked,
.wh-checkbox.is-indeterminate,
.wh-radio:checked,
.wh-radio.is-checked {
    border-color: var(--wh-mark-on);
    background: var(--wh-mark-on);
}

.wh-checkbox:checked::before,
.wh-checkbox:indeterminate::before,
.wh-checkbox.is-checked::before,
.wh-checkbox.is-indeterminate::before,
.wh-radio:checked::before,
.wh-radio.is-checked::before {
    opacity: 1;
}

.wh-checkbox:focus-visible,
.wh-radio:focus-visible,
.wh-checkbox.is-focus,
.wh-radio.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

.wh-checkbox.is-invalid,
.wh-radio.is-invalid,
.is-invalid > .wh-check > .wh-checkbox,
.is-invalid > .wh-check > .wh-radio {
    --wh-mark-invalid: var(--red-text);
}

.wh-checkbox:disabled,
.wh-radio:disabled {
    opacity: 0.55;
    cursor: default;
}

/* The row: box, then the label; the box sits on the first line */
.wh-check {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--wh-gap-tight);
    min-width: 0;
    color: var(--ink);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    cursor: pointer;
    user-select: none;
}

.wh-check > .wh-checkbox,
.wh-check > .wh-radio {
    margin-top: calc((var(--wh-lh) - var(--icon)) / 2);
}

.wh-check:has(> :disabled) {
    color: var(--muted);
    cursor: default;
}

/* Stacked list: 8 px between rows (5 px in Revit) */
.wh-checks {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--wh-gap-tight);
}

/* Children of a parent box start under the parent's label */
.wh-checks .wh-checks {
    padding-left: calc(var(--icon) + var(--wh-gap-tight));
}

/* Inline group: 16 px between items (10 px in Revit) */
.wh-checks-inline {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--wh-gap-tight) var(--wh-gap);
}


/* ── Radio tile: 40 px bordered rows for 5 or more options ────── */
/* Chosen = a dark ink ring and a red dot. The ring is an inset outline, so nothing moves.
   States: :hover / .is-hover, :active / .is-active, focus on the radio / .is-focus,
   :checked / .is-selected, disabled radio / .is-disabled, .is-invalid on the group. */

.wh-tiles {
    display: flex;
    flex-direction: column;
    gap: var(--wh-gap-tight);
}

.wh-tile {
    display: flex;
    align-items: flex-start;
    gap: var(--wh-gap-tight);
    min-height: var(--wh-h);
    min-width: 0;
    padding: calc((var(--wh-h) - var(--wh-lh)) / 2 - 1px) var(--wh-fx);
    border: 1px solid var(--edge);
    border-radius: var(--wh-r);
    outline: 1px solid transparent;
    outline-offset: -2px;
    background: var(--control);
    color: var(--ink);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), outline-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-tile > .wh-radio {
    margin-top: calc((var(--wh-lh) - var(--icon)) / 2);
}

.wh-tile:hover,
.wh-tile.is-hover {
    border-color: var(--edge-hover);
    background: var(--hover);
}

.wh-tile:active,
.wh-tile.is-active {
    border-color: var(--edge-hover);
    background: var(--press);
}

.wh-tile:has(> .wh-radio:focus-visible),
.wh-tile.is-focus {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-tile > .wh-radio:focus-visible {
    box-shadow: none;
}

.wh-tiles.is-invalid > .wh-tile {
    border-color: var(--red-text);
}

.wh-tile:has(> .wh-radio:checked),
.wh-tile.is-selected {
    border-color: var(--ink);
    outline-color: var(--ink);
}

.wh-tile:has(> .wh-radio:disabled),
.wh-tile.is-disabled {
    border-color: var(--edge);
    background: var(--disabled);
    color: var(--muted);
    cursor: default;
}

.wh-tile:has(> .wh-radio:disabled:checked),
.wh-tile.is-disabled.is-selected {
    border-color: var(--edge-hover);
    outline-color: var(--edge-hover);
}


/* ── Segmented: a red segment on a grey band track ────────────── */
/* 2–4 short options. Segments are 32 px in a 40 px track (24 in 32, 22 in 28, 18 in 24).
   Each label carries data-label, a bold copy that reserves the chosen width.
   States: :hover / .is-hover, :active / .is-active, :checked / .is-selected,
   focus on the radio / .is-focus on the track, :disabled. */

:root,
.wh-size-40 {
    --wh-seg-pad: 3px;
    --wh-seg-gap: var(--space-hair);
    --wh-seg-px: var(--space);
    --wh-seg-r: var(--radius-lg);
}

.wh-revit {
    --wh-seg-pad: 2px;
    --wh-seg-gap: 2px;
    --wh-seg-px: var(--space-revit);
    --wh-seg-r: var(--radius-md);
}

.wh-size-32 {
    --wh-seg-pad: 3px;
    --wh-seg-gap: var(--space-hair);
    --wh-seg-px: var(--space-tight);
    --wh-seg-r: var(--radius-md);
}

.wh-size-28 {
    --wh-seg-pad: 2px;
    --wh-seg-gap: 2px;
    --wh-seg-px: var(--space-revit);
    --wh-seg-r: var(--radius-md);
}

.wh-size-24 {
    --wh-seg-pad: 2px;
    --wh-seg-gap: 2px;
    --wh-seg-px: 6px;
    --wh-seg-r: var(--radius-md);
}

.wh-segmented {
    display: inline-flex;
    gap: var(--wh-seg-gap);
    max-width: 100%;
    padding: var(--wh-seg-pad);
    border: 1px solid var(--line);
    border-radius: var(--wh-seg-r);
    background: var(--band);
    vertical-align: middle;
    transition: border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-segmented > input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.wh-segmented > label {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: calc(var(--wh-h) - 2px - 2 * var(--wh-seg-pad));
    padding: 0 var(--wh-seg-px);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--ink-soft);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    font-weight: 400;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}

/* The bold copy: as wide as the chosen state, no height */
.wh-segmented > label::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

/* Not chosen: press-deep under the pointer, so it stands out on the band */
.wh-segmented > input:enabled + label:hover,
.wh-segmented > label.is-hover {
    background: var(--press-deep);
    color: var(--ink);
}

.wh-segmented > input:enabled + label:active,
.wh-segmented > label.is-active {
    background: linear-gradient(color-mix(in srgb, var(--ink) 8%, transparent), color-mix(in srgb, var(--ink) 8%, transparent)), var(--press-deep);
    color: var(--ink);
}

/* Chosen: red, on-red semibold */
.wh-segmented > input:checked + label,
.wh-segmented > label.is-selected {
    background: var(--red);
    color: var(--on-red);
    font-weight: 600;
}

.wh-segmented > input:enabled:checked + label:hover,
.wh-segmented > input:checked + label.is-hover,
.wh-segmented > label.is-selected.is-hover {
    background: var(--red-hover);
    color: var(--on-red);
}

.wh-segmented > input:enabled:checked + label:active,
.wh-segmented > input:checked + label.is-active,
.wh-segmented > label.is-selected.is-active {
    background: var(--red-press);
    color: var(--on-red);
}

/* Focus: the track takes the halo, like a field */
.wh-segmented:has(> input:focus-visible),
.wh-segmented.is-focus {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-segmented > input:disabled + label {
    opacity: 0.55;
    cursor: default;
}


/* ── Dropdown: a field box that opens a Würth menu ────────────── */
/* The trigger is a wh-field button. States: :hover / .is-hover, :focus / .is-focus,
   .is-open (aria-expanded), .is-invalid, :disabled / .is-disabled. */

.wh-select {
    width: 100%;
    margin: 0;
    font-family: var(--font-sans);
    font-weight: 400;
    text-align: left;
    cursor: pointer;
    user-select: none;
}

.wh-select:focus {
    outline: 0;
}

.wh-select.is-open,
.wh-select[aria-expanded="true"] {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-select.is-invalid.is-open,
.wh-select.is-invalid[aria-expanded="true"] {
    border-color: var(--red-text);
}

.wh-select:disabled,
.wh-select.is-disabled,
.wh-select.is-disabled:hover {
    border-color: var(--edge);
    background: var(--disabled);
    color: var(--muted);
    box-shadow: none;
    cursor: default;
}

.wh-select-value {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-select-more {
    flex: none;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.wh-select-more[hidden] {
    display: none;
}

.wh-select-chevron {
    margin-left: auto;
    transition: transform var(--duration-open) var(--ease), color var(--duration-fast) var(--ease);
}

.wh-select:hover:not(:disabled):not(.is-disabled) > .wh-select-chevron,
.wh-select.is-hover > .wh-select-chevron,
.wh-select.is-open > .wh-select-chevron,
.wh-select[aria-expanded="true"] > .wh-select-chevron {
    color: var(--ink);
}

.wh-select.is-open > .wh-select-chevron,
.wh-select[aria-expanded="true"] > .wh-select-chevron {
    transform: rotate(180deg);
}


/* ── Menu: the open list, on raised with a soft shadow ────────── */
/* Rows: :hover / .is-hover, .is-current (keyboard row), :active / .is-active,
   .is-selected (chosen, single), .is-checked (checkbox rows), .is-danger, .is-disabled. */

.wh-menu {
    position: fixed;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    min-width: var(--button-min);
    max-width: calc(100vw - var(--space) * 2);
    padding: var(--wh-gap-tight);
    border: 1px solid var(--line);
    border-radius: var(--wh-r-lg);
    background: var(--raised);
    box-shadow: var(--shadow-menu);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transform: translateY(calc(var(--space-hair) * -1));
    pointer-events: none;
    transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease), visibility 0s linear var(--duration-fast);
}

.wh-menu.is-above {
    transform: translateY(var(--space-hair));
}

.wh-menu.is-open,
.wh-menu.is-static {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease), visibility 0s;
}

.wh-menu.is-static {
    position: relative;
    z-index: auto;
    max-width: none;
}

.wh-menu-search {
    flex: none;
    padding: 0 calc(var(--wh-gap-tight) - 1px);
    margin-bottom: var(--wh-gap-tight);
}

/* The search box takes the menu width; it never widens the menu */
.wh-menu-search > input {
    width: 0;
}

.wh-menu-list {
    flex: 1 1 auto;
    min-height: 0;
    max-height: calc(var(--wh-h) * 8);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.wh-menu-items {
    display: flex;
    flex-direction: column;
}

.wh-menu-item {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    width: 100%;
    min-height: var(--wh-h);
    margin: 0;
    padding: 0 var(--wh-gap-tight);
    border: 0;
    border-radius: var(--wh-r);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    font-weight: 400;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease);
}

/* Rows on raised: hover and press greys a step stronger in dark, where raised is already lighter
   than the page, so the row under the pointer still shows (the calendar's days use them too) */
.wh-menu,
.wh-calendar {
    --wh-row-hover: var(--hover);
    --wh-row-press: var(--press);
}

[data-theme="dark"] :is(.wh-menu, .wh-calendar) {
    --wh-row-hover: var(--press);
    --wh-row-press: var(--press-deep);
}

.wh-menu-item:hover:not(:disabled):not(.is-disabled),
.wh-menu-item.is-hover,
.wh-menu-item.is-current {
    background: var(--wh-row-hover);
}

/* While the keyboard leads, the row under a resting pointer stays plain */
.wh-menu.is-keys .wh-menu-item:hover:not(.is-current) {
    background: transparent;
}

.wh-menu-item:active:not(:disabled):not(.is-disabled),
.wh-menu-item.is-active {
    background: var(--wh-row-press);
}

.wh-menu-item:focus {
    outline: 0;
}

.wh-menu-item:focus-visible,
.wh-menu-item.is-focus {
    background: var(--wh-row-hover);
    box-shadow: var(--focus-ring);
}

.wh-menu-item.is-selected {
    font-weight: 600;
}

.wh-menu-item.is-danger {
    color: var(--red-text);
}

.wh-menu-item:disabled,
.wh-menu-item.is-disabled {
    opacity: 0.55;
    cursor: default;
}

/* The label; a hidden semibold copy reserves the chosen width */
.wh-menu-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wh-menu-text[data-label]::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.wh-menu-tick {
    color: var(--red-text);
    visibility: hidden;
}

.wh-menu-item.is-selected > .wh-menu-tick {
    visibility: visible;
}

/* Checkbox rows: the shared wh-checkbox box (20-choice.css) before the text; the row clicks */
.wh-menu-item > .wh-checkbox {
    pointer-events: none;
}

.wh-menu-empty {
    display: flex;
    align-items: center;
    min-height: var(--wh-h);
    padding: 0 var(--wh-gap-tight);
    color: var(--muted);
    white-space: nowrap;
}


/* ── Menu variants: groups, a second line, a leading icon ─────── */
/* A group (wh-menu-group, role="group") starts with a muted semibold heading on the row text's line.
   A row with a second line (has-detail) holds wh-menu-label over a muted wh-menu-detail at the
   label size. A leading icon (wh-menu-icon) takes the row's text colour. Disabled rows fade. */

.wh-menu-heading {
    display: block;
    min-width: 0;
    overflow: hidden;
    padding: var(--wh-gap-tight) var(--wh-gap-tight) var(--space-hair);
    color: var(--muted);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-menu-group:first-child > .wh-menu-heading {
    padding-top: var(--space-hair);
}

.wh-menu-item.has-detail {
    padding-top: var(--space-hair);
    padding-bottom: var(--space-hair);
}

.wh-menu-label,
.wh-menu-detail {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wh-menu-label[data-label]::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.wh-menu-detail {
    color: var(--muted);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 400;
}

.wh-menu-icon {
    flex: none;
}


/* ── Combobox: a dropdown you type into ───────────────────────── */
/* wh-field wh-select is-combo holds a text input (role="combobox") and the chevron; the whole box
   clicks. Typing filters the menu. With a unit (has-unit) the input is as wide as its text, so the
   unit follows the value as in any dropdown. States as the dropdown, plus :focus-within. */

.wh-select.is-combo {
    cursor: text;
    user-select: auto;
}

.wh-select.is-combo > input {
    flex: 1 1 auto;
    text-overflow: ellipsis;
}

.wh-select.is-combo.has-unit > input {
    flex: 0 1 auto;
    width: var(--wh-combo-width, 100%);
}

/* The unit a word space after the typed value, as in a dropdown */
.wh-select.is-combo.has-unit > .wh-unit {
    margin-left: calc(0.25em - var(--wh-gap-tight));
}

.wh-select.is-combo > .wh-select-chevron {
    cursor: pointer;
}

.wh-select.is-combo.is-disabled,
.wh-select.is-combo.is-disabled > .wh-select-chevron {
    cursor: default;
}

/* A leading icon in the field takes the value's colour, as in the menu */
.wh-select > .wh-select-icon {
    color: inherit;
}


/* ── Date field: a field box with a calendar icon ─────────────── */
/* The field is wh-field wh-date with a text input; .is-open while the calendar shows. */

.wh-date {
    cursor: text;
}

.wh-date.is-open {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-date.is-invalid.is-open {
    border-color: var(--red-text);
}

.wh-date > input {
    font-variant-numeric: tabular-nums;
}

.wh-date-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--icon);
    height: var(--icon);
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease);
}

.wh-date-toggle:focus {
    outline: 0;
}

.wh-date:hover:not(.is-disabled) > .wh-date-toggle,
.wh-date.is-hover > .wh-date-toggle,
.wh-date.is-open > .wh-date-toggle {
    color: var(--ink);
}

.wh-date.is-disabled > .wh-date-toggle {
    color: var(--muted);
    cursor: default;
}


/* ── Calendar: the Würth popup, Monday first ──────────────────── */
/* Days: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus,
   .is-today (ink outline), .is-selected (red), .is-other (another month). */

.wh-calendar {
    --wh-day: min(var(--wh-h), var(--control-32));
    min-width: 0;
    font-size: min(var(--wh-fs), 14px);
    line-height: var(--wh-label-lh);
}

.wh-cal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--wh-gap-tight);
    margin-bottom: var(--space-hair);
}

.wh-cal-head > .wh-icon-btn {
    width: var(--wh-day);
    height: var(--wh-day);
}

.wh-cal-month {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    font-weight: 600;
}

.wh-cal-grid {
    display: grid;
    grid-template-columns: repeat(7, var(--wh-day));
    gap: var(--space-hair);
}

.wh-cal-dayname {
    display: flex;
    align-items: center;
    justify-content: center;
    height: calc(var(--wh-day) - var(--space-tight));
    color: var(--muted);
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
}

.wh-cal-day {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--wh-day);
    height: var(--wh-day);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--wh-r);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: inherit;
    line-height: inherit;
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-cal-day:hover,
.wh-cal-day.is-hover {
    background: var(--wh-row-hover, var(--hover));
}

.wh-cal-day:active,
.wh-cal-day.is-active {
    background: var(--wh-row-press, var(--press));
}

.wh-cal-day.is-other {
    color: var(--muted);
}

.wh-cal-day.is-today {
    box-shadow: inset 0 0 0 1px var(--ink);
    font-weight: 600;
}

.wh-cal-day:focus {
    outline: 0;
}

.wh-cal-day:focus-visible,
.wh-cal-day.is-focus {
    z-index: 1;
    box-shadow: var(--focus-ring);
}

.wh-cal-day.is-today:focus-visible,
.wh-cal-day.is-today.is-focus {
    box-shadow: inset 0 0 0 1px var(--ink), var(--focus-ring);
}

.wh-cal-day.is-selected {
    background: var(--red);
    color: var(--on-red);
    box-shadow: none;
    font-weight: 600;
}

.wh-cal-day.is-selected:hover,
.wh-cal-day.is-selected.is-hover {
    background: var(--red-hover);
}

.wh-cal-day.is-selected:active,
.wh-cal-day.is-selected.is-active {
    background: var(--red-press);
}

.wh-cal-day.is-selected:focus-visible,
.wh-cal-day.is-selected.is-focus {
    box-shadow: var(--focus-ring);
}


/* ── Slider: white thumb, red fill ────────────────────────────── */
/* A native range input on a 4 px track. The red fill runs up to the thumb, or between two
   thumbs (is-dual), from --wh-range-from and --wh-range-to (0 to 1); WurthUI.slider keeps them
   and the value fields in step. The thumb is half the control height: 20, 16, 14, 12 px.
   States: :hover / .is-hover, :active / .is-dragging, :focus-visible / .is-focus, :disabled. */

.wh-range {
    --wh-thumb-size: calc(var(--wh-h) / 2);
    --wh-range-from: 0;
    --wh-range-to: 0;
    position: relative;
    isolation: isolate;
    flex: 1 1 auto;
    min-width: calc(var(--wh-h) * 2);
    height: var(--wh-h);
    cursor: pointer;
    touch-action: none;
}

/* Track and fill */
.wh-range::before,
.wh-range::after {
    content: "";
    position: absolute;
    top: 50%;
    height: var(--space-hair);
    margin-top: calc(var(--space-hair) / -2);
    border-radius: var(--radius-pill);
}

.wh-range::before {
    left: 0;
    right: 0;
    background: var(--edge);
}

.wh-range::after {
    left: 0;
    width: calc(var(--wh-thumb-size) / 2 + (100% - var(--wh-thumb-size)) * var(--wh-range-to));
    background: var(--red);
    transition: background-color var(--duration-fast) var(--ease);
}

.wh-range.is-dual::after {
    left: calc(var(--wh-thumb-size) / 2 + (100% - var(--wh-thumb-size)) * var(--wh-range-from));
    width: calc((100% - var(--wh-thumb-size)) * (var(--wh-range-to) - var(--wh-range-from)));
}

/* The input spans the track; only its thumb takes the pointer, so two can overlap */
.wh-range > input[type=range] {
    --wh-thumb-edge: 0 0 0 0 transparent;
    --wh-thumb-halo: 0 0 0 0 transparent;
    --wh-thumb-cursor: grab;
    position: absolute;
    z-index: 1;
    top: 50%;
    left: 0;
    width: 100%;
    height: var(--wh-thumb-size);
    margin: calc(var(--wh-thumb-size) / -2) 0 0;
    padding: 0;
    background: transparent;
    -webkit-appearance: none;
    appearance: none;
    pointer-events: none;
}

.wh-range > input[type=range]:focus {
    outline: 0;
}

.wh-range > input[type=range]::-webkit-slider-runnable-track {
    height: var(--wh-thumb-size);
    border: 0;
    background: transparent;
}

.wh-range > input[type=range]::-moz-range-track {
    height: var(--wh-thumb-size);
    border: 0;
    background: transparent;
}

.wh-range > input[type=range]::-webkit-slider-thumb {
    width: var(--wh-thumb-size);
    height: var(--wh-thumb-size);
    border: 0;
    border-radius: 50%;
    background: var(--thumb);
    box-shadow: var(--wh-thumb-edge), var(--shadow-thumb), var(--wh-thumb-halo);
    cursor: var(--wh-thumb-cursor);
    pointer-events: auto;
    -webkit-appearance: none;
    appearance: none;
    transition: box-shadow var(--duration-fast) var(--ease);
}

.wh-range > input[type=range]::-moz-range-thumb {
    width: var(--wh-thumb-size);
    height: var(--wh-thumb-size);
    border: 0;
    border-radius: 50%;
    background: var(--thumb);
    box-shadow: var(--wh-thumb-edge), var(--shadow-thumb), var(--wh-thumb-halo);
    cursor: var(--wh-thumb-cursor);
    pointer-events: auto;
    transition: box-shadow var(--duration-fast) var(--ease);
}

/* Hover: a 2 px edge, one step darker */
.wh-range > input[type=range]:enabled:hover,
.wh-range > input[type=range].is-hover {
    --wh-thumb-edge: 0 0 0 2px var(--muted);
}

/* Dragging: a 2 px edge, two steps darker */
.wh-range > input[type=range]:enabled:active,
.wh-range > input[type=range].is-dragging {
    --wh-thumb-edge: 0 0 0 2px var(--ink-soft);
    --wh-thumb-cursor: grabbing;
}

/* Focus: the light grey halo around the thumb, for the keyboard */
.wh-range > input[type=range]:focus-visible,
.wh-range > input[type=range].is-focus {
    --wh-thumb-halo: var(--focus-ring);
}

.wh-range:has(> input.is-dragging) {
    cursor: grabbing;
}

/* The thumb being moved sits on top of the other */
.wh-range > input[type=range]:active,
.wh-range > input[type=range]:focus,
.wh-range > input[type=range].is-dragging {
    z-index: 2;
}

/* Disabled: grey fill, no pointer */
.wh-range:has(> input:disabled),
.wh-range.is-disabled {
    cursor: default;
}

.wh-range:has(> input:disabled)::after,
.wh-range.is-disabled::after {
    background: var(--edge-hover);
}

.wh-range > input[type=range]:disabled {
    --wh-thumb-cursor: default;
}

.wh-range > input[type=range]:disabled::-webkit-slider-thumb {
    background: var(--disabled);
    box-shadow: 0 0 0 1px var(--edge);
}

.wh-range > input[type=range]:disabled::-moz-range-thumb {
    background: var(--disabled);
    box-shadow: 0 0 0 1px var(--edge);
}


/* ── With a value: the slider and a 128 px field on one row ───── */

.wh-slider {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
}

.wh-slider > .wh-field {
    flex: none;
    width: var(--button-min);
}


/* ── Bottom and top: the slider on its own row, a field under each end ── */

.wh-slider-range {
    display: grid;
    grid-template-columns: var(--button-min) minmax(0, 1fr) var(--button-min);
    gap: var(--wh-gap-tight);
    min-width: 0;
}

.wh-slider-range > .wh-range {
    grid-column: 1 / -1;
}

.wh-slider-range > .wh-slider-end {
    grid-column: 3;
}

.wh-slider-range > .wh-error {
    grid-column: 1 / -1;
    margin: 0;
}

.wh-slider-range > .wh-error[hidden] {
    display: none;
}


/* ── File import: the Import button and the card drop zone ────── */
/* The button is a standard button on a <label> that holds the file input, so Tab, Enter and
   Space reach it without script. The drop zone is the card that takes a dropped file.
   States: the button's own, plus :focus-visible on the input, :disabled on the input,
   .is-busy (spinner), and .is-dragover on the card while a file is over it. */

.wh-import {
    position: relative;
}

.wh-import > input[type=file] {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    opacity: 0;
    pointer-events: none;
}

.wh-import:has(> input:focus-visible) {
    outline: 0;
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-import:has(> input:disabled),
.wh-import.is-disabled {
    opacity: 0.55;
    cursor: default;
    pointer-events: none;
}

/* The card: a red dashed outline and a faint red wash while a file is over it */
.wh-dropzone {
    position: relative;
}

.wh-dropzone::after {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: 3;
    border: 2px dashed var(--red);
    border-radius: inherit;
    background: color-mix(in srgb, var(--red) 4%, transparent);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-fast) var(--ease);
}

.wh-dropzone.is-dragover::after {
    opacity: 1;
}


/* ── Chip: a choice you add, order and remove ─────────────────── */
/* The objective pills. A stack (wh-chips) wraps chips 8 px apart (5 px in Revit). Chips are 32 px on
   the web at 14 px semibold and 24 px in Revit at 12 px, with pill ends.
   Not chosen (a button): control fill, edge border, ink text, a + at the right in a round inner
   button. Chosen (is-chosen): the dark chosen container, ink fill and on-ink text, a grip at the left
   to drag it into order and an x at the right that removes it from the choice.
   The round inner buttons and the grip sit 4 px in (3 px in Revit), concentric with the pill's
   ends; a label without a grip starts (height − icon) / 2 + 4 px in, as in a button.
   States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus, :disabled /
   .is-disabled, .is-dragging (the chosen chip being moved). */

.wh-chips {
    --wh-chip-h: var(--control-32);
    --wh-chip-in: var(--space-hair);
    --wh-chip-icon: var(--icon);
    --wh-chip-fs: 14px;
    --wh-chip-lh: 20px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-tight);
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.wh-revit .wh-chips,
.wh-chips.wh-revit {
    --wh-chip-h: var(--control-24);
    --wh-chip-in: 3px;
    --wh-chip-icon: var(--icon-sm);
    --wh-chip-fs: 12px;
    --wh-chip-lh: 16px;
    gap: var(--space-revit-tight);
}

.wh-chip {
    --wh-icon: var(--wh-chip-icon);
    --wh-chip-button: calc(var(--wh-chip-h) - 2 * var(--wh-chip-in));
    position: relative;
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: var(--space-hair);
    min-width: 0;
    max-width: 100%;
    height: var(--wh-chip-h);
    margin: 0;
    padding: 0 calc(var(--wh-chip-in) - 1px) 0 calc((var(--wh-chip-h) - var(--wh-chip-icon)) / 2 + var(--space-hair) - 1px);
    border: 1px solid var(--edge);
    border-radius: var(--radius-pill);
    background: var(--control);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--wh-chip-fs);
    line-height: var(--wh-chip-lh);
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-chip-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The round inner button: the + to add, the x to remove */
.wh-chip-action {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: var(--wh-chip-button);
    height: var(--wh-chip-button);
    margin: 0 0 0 var(--space-hair);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease);
}

.wh-chip-action:focus {
    outline: 0;
}

/* The grip: the chosen chip's handle for dragging it into order */
.wh-chip-grip {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: var(--wh-chip-button);
    height: var(--wh-chip-button);
    color: color-mix(in srgb, var(--on-ink) 65%, transparent);
    cursor: grab;
}

/* Not chosen: hover one shade darker, the + square two */
.wh-chip:not(.is-chosen):hover:not(:disabled):not(.is-disabled),
.wh-chip.is-hover:not(.is-chosen) {
    border-color: var(--edge-hover);
    background: var(--hover);
}

.wh-chip:not(.is-chosen):hover:not(:disabled):not(.is-disabled) > .wh-chip-action,
.wh-chip.is-hover:not(.is-chosen) > .wh-chip-action {
    background: var(--press);
}

.wh-chip:not(.is-chosen):active:not(:disabled):not(.is-disabled),
.wh-chip.is-active:not(.is-chosen) {
    border-color: var(--edge-hover);
    background: var(--press);
}

.wh-chip:not(.is-chosen):active:not(:disabled):not(.is-disabled) > .wh-chip-action,
.wh-chip.is-active:not(.is-chosen) > .wh-chip-action {
    background: var(--press-deep);
}

/* Chosen: the dark chosen container */
.wh-chip.is-chosen {
    padding-left: calc(var(--wh-chip-in) - 1px);
    border-color: var(--ink);
    background: var(--ink);
    color: var(--on-ink);
    cursor: grab;
    touch-action: none;
}

.wh-chip.is-chosen:hover:not(.is-disabled),
.wh-chip.is-chosen.is-hover {
    border-color: color-mix(in srgb, var(--ink) 88%, var(--surface));
    background: color-mix(in srgb, var(--ink) 88%, var(--surface));
}

.wh-chip.is-chosen:active:not(.is-disabled),
.wh-chip.is-chosen.is-active {
    border-color: color-mix(in srgb, var(--ink) 78%, var(--surface));
    background: color-mix(in srgb, var(--ink) 78%, var(--surface));
}

.wh-chip.is-chosen > .wh-chip-action:hover:not(:disabled),
.wh-chip.is-chosen > .wh-chip-action.is-hover {
    background: color-mix(in srgb, var(--on-ink) 18%, transparent);
}

.wh-chip.is-chosen > .wh-chip-action:active:not(:disabled),
.wh-chip.is-chosen > .wh-chip-action.is-active {
    background: color-mix(in srgb, var(--on-ink) 28%, transparent);
}

/* Focus: the halo, for the keyboard */
.wh-chip:focus {
    outline: 0;
}

.wh-chip:focus-visible,
.wh-chip.is-focus {
    box-shadow: var(--focus-ring);
}

.wh-chip:not(.is-chosen):focus-visible,
.wh-chip.is-focus:not(.is-chosen) {
    border-color: var(--edge-hover);
}

/* Dragging: the chip lifts while it is moved; the others make room as it passes */
.wh-chip.is-dragging {
    z-index: 1;
    box-shadow: var(--shadow-menu);
    cursor: grabbing;
}

.wh-chip.is-dragging > .wh-chip-grip {
    cursor: grabbing;
}

body.is-dragging-chip {
    cursor: grabbing;
    user-select: none;
}

/* Disabled: faded, no pointer */
.wh-chip:disabled,
.wh-chip.is-disabled,
.wh-chip-action:disabled {
    opacity: 0.55;
    cursor: default;
}

.wh-chip.is-disabled > .wh-chip-grip {
    cursor: default;
}


/* ── Header: the web app bar ──────────────────────────────────── */
/* 56 px on surface with a 2 px red line under it. Logo, bar, app name, nav links on the left;
   EN | DE, the user and Sign out on the right.
   Links: :hover / .is-hover, :focus-visible / .is-focus, [aria-current="page"] / .is-current.
   Widths: under 992 px the user name goes (.is-medium), under 576 px the app name and the nav go
   too (.is-phone). The .is-* classes force a width on the spec sheets. */

.wh-header {
    position: sticky;
    top: env(safe-area-inset-top, 0px);
    z-index: 40;
    display: flex;
    align-items: center;
    gap: var(--space);
    height: var(--header);
    min-width: 0;
    padding: 0 var(--space);
    border-bottom: 2px solid var(--red);
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 24px;
}

/* Home link: logo, a grey bar, the app name */
.wh-header-brand {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--space-tight);
    margin: calc(-1 * var(--space-hair));
    padding: var(--space-hair);
    border-radius: var(--radius-sm);
    color: var(--muted);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-header-brand > .wh-logo {
    flex: none;
    height: 26px;
}

.wh-header-divider {
    flex: none;
    width: 1px;
    height: 1.25em;
    background: var(--edge-hover);
}

.wh-header-brand:hover,
.wh-header-brand.is-hover {
    color: var(--ink);
}

.wh-header-brand:focus-visible,
.wh-header-brand.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

/* Nav links: ink text, the current page in red-text */
.wh-header-nav {
    display: flex;
    align-items: center;
    gap: var(--space);
    min-width: 0;
}

.wh-header-link {
    display: inline-flex;
    align-items: center;
    height: var(--control-32);
    margin: 0 calc(-1 * var(--space-hair));
    padding: 0 var(--space-hair);
    border-radius: var(--radius-sm);
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-header-link:hover,
.wh-header-link.is-hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.wh-header-link[aria-current="page"],
.wh-header-link.is-current {
    color: var(--red-text);
}

.wh-header-link:focus-visible,
.wh-header-link.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}

/* Right end: EN | DE, the user, Sign out, 8 px apart */
.wh-header-end {
    display: flex;
    align-items: center;
    gap: var(--space-tight);
    min-width: 0;
    margin-left: auto;
}

.wh-header-end > * {
    flex: none;
}

.wh-header-user {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    color: var(--muted);
    font-size: 14px;
    line-height: 20px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Medium: the user name goes */
@media (max-width: 991.98px) {
    .wh-header-user {
        display: none;
    }
}

.wh-header.is-medium .wh-header-user,
.wh-header.is-phone .wh-header-user {
    display: none;
}

/* Phone: logo, EN | DE and Sign out only */
@media (max-width: 575.98px) {
    .wh-header {
        gap: var(--space-tight);
    }

    .wh-header-divider,
    .wh-header-app,
    .wh-header-nav {
        display: none;
    }
}

.wh-header.is-phone {
    gap: var(--space-tight);
}

.wh-header.is-phone .wh-header-divider,
.wh-header.is-phone .wh-header-app,
.wh-header.is-phone .wh-header-nav {
    display: none;
}


/* ── UpperBar: the Revit window's top bar ─────────────────────── */
/* 44 px on surface with a 2 px red line under it. The logo at the left edge, tools and EN | DE at
   the right. Put it first inside the window's wh-revit root; its edges follow --wh-gap (10 px). */

.wh-upper {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--wh-gap-tight);
    height: var(--upper-bar);
    min-width: 0;
    padding: 0 var(--wh-gap);
    border-bottom: 2px solid var(--red);
    background: var(--surface);
    color: var(--ink);
}

.wh-upper > .wh-logo {
    flex: none;
    height: 20px;
}

.wh-upper-end {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--wh-gap-tight);
    margin-left: auto;
}


/* ── Steps: the band under the header ─────────────────────────── */
/* The step names only, separated by grey chevrons. Done steps are ink, the current step is
   red-text semibold, upcoming steps are muted. Each name carries data-label, a bold copy that
   reserves the current width, so nothing moves when the step changes.
   Steps: .is-done, .is-current (with aria-current="step"), upcoming = no class.
   States: :hover / .is-hover, :focus-visible / .is-focus. */

:root {
    --wh-steps-h: var(--steps-band);
    --wh-step-h: var(--control-32);
    --wh-step-fs: 14px;
    --wh-step-lh: 20px;
}

.wh-revit {
    --wh-steps-h: var(--steps-band-revit);
    --wh-step-h: var(--control-28);
    --wh-step-fs: 13px;
    --wh-step-lh: 18px;
}

.wh-steps {
    position: sticky;
    top: calc(env(safe-area-inset-top, 0px) + var(--header));
    z-index: 30;
    display: flex;
    align-items: center;
    min-width: 0;
    min-height: var(--wh-steps-h);
    padding: 0 var(--wh-gap);
    border-bottom: 1px solid var(--line);
    background: var(--band);
}

.wh-revit .wh-steps,
.wh-steps.wh-revit {
    position: static;
}

/* The list scrolls sideways on narrow screens; its room around the steps keeps the focus halo whole */
.wh-steps-list {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
    margin: calc(-1 * var(--space-hair)) calc(-1 * var(--space-tight));
    padding: var(--space-hair) var(--space-tight);
    overflow-x: auto;
    scrollbar-width: none;
    list-style: none;
    font-size: var(--wh-step-fs);
    line-height: var(--wh-step-lh);
    white-space: nowrap;
}

.wh-steps-list::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.wh-steps-list > li {
    display: flex;
    flex: none;
    align-items: center;
}

.wh-step-sep {
    color: var(--edge-hover);
}

/* A step: upcoming by default. A link, a button or (not clickable) a span */
.wh-step {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    height: var(--wh-step-h);
    margin: 0 calc(-1 * var(--space-hair));
    padding: 0 var(--space-hair);
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--muted);
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    font-weight: 400;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

/* The bold copy: as wide as the current state, no height */
.wh-step::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.wh-step.is-done {
    color: var(--ink);
}

.wh-step.is-current {
    color: var(--red-text);
    font-weight: 600;
    cursor: default;
}

.wh-step:not(.is-current):hover,
.wh-step.is-hover {
    color: var(--ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.wh-step:focus-visible,
.wh-step.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}


/* ── Tabs: underline tabs on a 1 px line ──────────────────────── */
/* The open tab is ink semibold with a 3 px red line on the baseline; the others are muted.
   Sides are (height − 16) / 2: 12 px at 40, 8 at 32, 6 at 28. The row is pulled left by that much,
   so the first label, its red line and the baseline start on the content edge.
   Each label carries data-label, a bold copy that reserves the open width.
   The row scrolls sideways, so it keeps 4 px of room on every side for the focus halo (the bottom
   too); the baseline is drawn at the tabs' foot, above that room.
   States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus,
   [aria-selected="true"] / .is-selected. */

.wh-tabs {
    --wh-tab-px: calc((var(--wh-h) - var(--icon)) / 2);
    position: relative;
    display: flex;
    min-width: 0;
    margin: calc(-1 * var(--space-hair)) calc(-1 * var(--space-hair)) calc(-1 * var(--space-hair)) calc(-1 * (var(--wh-tab-px) + var(--space-hair)));
    padding: var(--space-hair);
    overflow-x: auto;
    scrollbar-width: none;
    background: linear-gradient(var(--line), var(--line)) calc(var(--space-hair) + var(--wh-tab-px)) calc(100% - var(--space-hair)) / calc(100% - 2 * var(--space-hair) - var(--wh-tab-px)) 1px no-repeat local;
}

.wh-tabs::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.wh-tab {
    position: relative;
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: var(--wh-gap-tight);
    height: var(--wh-h);
    margin: 0;
    padding: 0 var(--wh-tab-px);
    border: 0;
    border-bottom: 1px solid transparent;
    border-radius: var(--wh-r) var(--wh-r) 0 0;
    background: transparent;
    background-clip: padding-box;
    color: var(--muted);
    font-family: var(--font-sans);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    font-weight: 400;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: color var(--duration-fast) var(--ease), background-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

/* The red line: under the label and count, on the baseline */
.wh-tab::after {
    content: "";
    position: absolute;
    left: var(--wh-tab-px);
    right: var(--wh-tab-px);
    bottom: -1px;
    height: 3px;
    background: var(--red);
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease);
}

.wh-tab-label {
    display: inline-flex;
    flex-direction: column;
    min-width: 0;
}

/* The bold copy: as wide as the open state, no height */
.wh-tab-label::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.wh-tab-count {
    color: var(--muted);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

.wh-tab:hover,
.wh-tab.is-hover {
    background-color: var(--hover);
    color: var(--ink);
}

.wh-tab:active,
.wh-tab.is-active {
    background-color: var(--press);
    color: var(--ink);
}

.wh-tab[aria-selected="true"],
.wh-tab.is-selected {
    color: var(--ink);
}

.wh-tab[aria-selected="true"] > .wh-tab-label,
.wh-tab.is-selected > .wh-tab-label {
    font-weight: 600;
}

.wh-tab[aria-selected="true"]::after,
.wh-tab.is-selected::after {
    opacity: 1;
}

.wh-tab:focus-visible,
.wh-tab.is-focus {
    outline: 0;
    box-shadow: var(--focus-ring);
}


/* ── Action bar: the bottom band ──────────────────────────────── */
/* Band grey with a line on top. Back on the left, the step's one primary action last on the right
   (in wh-actionbar-end). Buttons share one minimum width. In a Revit window (wh-revit) the edges are
   10 px and the buttons 32 px, 8 px apart (10-button.css). is-fill wh-size-40 makes the Varifix
   panel's one big button: 40 px and full width.
   .is-fill: every button grows to share the row; phones get it on their own. */

.wh-actionbar {
    --wh-actionbar-min: var(--button-min);
    position: sticky;
    bottom: env(safe-area-inset-bottom, 0px);
    z-index: 30;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
    padding: var(--wh-gap);
    border-top: 1px solid var(--line);
    background: var(--band);
}

/* Revit: the bar sits at the bottom of the window's own layout; smaller shared width */
.wh-revit .wh-actionbar,
.wh-actionbar.wh-revit {
    --wh-actionbar-min: var(--button-min-revit);
    position: static;
}

.wh-actionbar-end {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
    margin-left: auto;
}

.wh-actionbar .wh-btn {
    min-width: var(--wh-actionbar-min);
}

/* Fill: the buttons share the row, and each takes it whole when the labels do not fit */
.wh-actionbar.is-fill > .wh-btn,
.wh-actionbar.is-fill > .wh-actionbar-end,
.wh-actionbar.is-fill > .wh-actionbar-end > .wh-btn {
    flex: 1 1 var(--wh-actionbar-min);
}

.wh-actionbar.is-fill > .wh-actionbar-end {
    margin-left: 0;
}

@media (max-width: 575.98px) {
    .wh-actionbar > .wh-btn,
    .wh-actionbar > .wh-actionbar-end,
    .wh-actionbar > .wh-actionbar-end > .wh-btn {
        flex: 1 1 var(--wh-actionbar-min);
    }

    .wh-actionbar > .wh-actionbar-end {
        margin-left: 0;
    }
}


/* ── Card: the content box ────────────────────────────────────── */
/* 1 px line border, radius-lg (radius-md in Revit), 16 px padding (10 px in Revit), no shadow.
   The card you open from a list (wh-card-open) adds shadow-card and deepens it on hover.
   States on wh-card-open: :hover / .is-hover, focus on its wh-card-link / .is-focus. */

:root {
    --wh-head-fs: 16px;
    --wh-head-lh: 24px;
}

.wh-revit {
    --wh-head-fs: 14px;
    --wh-head-lh: 20px;
}

.wh-card {
    display: block;
    min-width: 0;
    padding: var(--wh-gap);
    border: 1px solid var(--line);
    border-radius: var(--wh-r-lg);
    background: var(--surface);
    color: var(--ink);
}

/* Flush: a table runs to the card's border. The card drops its padding and clips the header band to
   its corners; the table's outer cells keep the 16 px edge (10 px in Revit) and its last row leaves
   its line to the card's border (43-table.css), so no two lines meet. A head keeps the padding. */
.wh-card-flush {
    padding: 0;
    overflow: hidden;
}

.wh-card-flush > .wh-card-head {
    margin: 0;
    padding: var(--wh-gap) var(--wh-gap) var(--wh-gap-tight);
}

.wh-card-flush > .wh-table-wrap {
    margin: 0;
    padding: 0;
}

/* Head: the title on the left, a 32 px button (28 px in Revit) or icon button on the right */
.wh-card-head {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
    min-height: var(--wh-h);
    margin-bottom: var(--wh-gap-tight);
}

.wh-card-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    color: var(--ink);
    font-size: var(--wh-head-fs);
    line-height: var(--wh-head-lh);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-card-head > :not(.wh-card-title) {
    flex: none;
}

/* Opened from a list: a soft shadow, deeper under the pointer; the title link covers the card */
.wh-card-open {
    position: relative;
    box-shadow: var(--shadow-card);
    cursor: pointer;
    transition: box-shadow var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease);
}

/* Hover: the deeper shadow, and the border one step darker so it also reads in dark */
.wh-card-open:hover,
.wh-card-open.is-hover {
    border-color: var(--edge);
    box-shadow: var(--shadow-card-hover);
}

.wh-card-link {
    color: inherit;
    text-decoration: none;
    outline: 0;
}

.wh-card-link::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* Controls inside the card stay above the link */
.wh-card-open :is(button, input, select, textarea, a:not(.wh-card-link)) {
    position: relative;
    z-index: 1;
}

.wh-card-open:has(.wh-card-link:focus-visible),
.wh-card-open.is-focus {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring), var(--shadow-card);
}

.wh-card-open.is-hover.is-focus,
.wh-card-open:hover:has(.wh-card-link:focus-visible) {
    box-shadow: var(--focus-ring), var(--shadow-card-hover);
}


/* ── Section: a collapsible head and its fold ─────────────────── */
/* The whole head row clicks. Label left; the grey count right-aligned next to the chevron at the
   far right. Top level (wh-section-head): 40 px with a line under it, 28 px in Revit. Next level
   (wh-subsection-head): 32 px at 14 px, 24 px at 12 px in Revit, no line.
   The head is pulled out by the tight gap on both sides, so its label stays on the content edge
   and the hover grey has room; the line runs from content edge to content edge.
   The chevron points down when closed and up when open. The fold slides over duration-open.
   States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus,
   [aria-expanded="true"] = open. */

:root {
    --wh-section-h: var(--control-40);
    --wh-sub-h: var(--control-32);
    --wh-sub-fs: 14px;
    --wh-sub-lh: 20px;
}

.wh-revit {
    --wh-section-h: var(--control-28);
    --wh-sub-h: var(--control-24);
    --wh-sub-fs: 12px;
    --wh-sub-lh: 16px;
}

.wh-section-head,
.wh-subsection-head {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    width: calc(100% + 2 * var(--wh-gap-tight));
    min-width: 0;
    margin: 0 calc(-1 * var(--wh-gap-tight));
    padding: 0 var(--wh-gap-tight);
    border: 0;
    border-radius: var(--wh-r);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-sans);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-section-head {
    height: var(--wh-section-h);
    border-radius: var(--wh-r) var(--wh-r) 0 0;
    font-size: var(--wh-head-fs);
    line-height: var(--wh-head-lh);
}

/* The line under a top-level head, on the content edges */
.wh-section-head::after {
    content: "";
    position: absolute;
    left: var(--wh-gap-tight);
    right: var(--wh-gap-tight);
    bottom: 0;
    height: 1px;
    background: var(--line);
}

.wh-subsection-head {
    height: var(--wh-sub-h);
    font-size: var(--wh-sub-fs);
    line-height: var(--wh-sub-lh);
}

.wh-section-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-section-count {
    flex: none;
    margin-left: auto;
    color: var(--muted);
    font-size: var(--wh-sub-fs);
    line-height: var(--wh-sub-lh);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.wh-section-chevron {
    flex: none;
    color: var(--muted);
    transition: transform var(--duration-open) var(--ease), color var(--duration-fast) var(--ease);
}

.wh-section-label + .wh-section-chevron {
    margin-left: auto;
}

[aria-expanded="true"] > .wh-section-chevron {
    transform: rotate(180deg);
}

.wh-section-head:hover,
.wh-subsection-head:hover,
.wh-section-head.is-hover,
.wh-subsection-head.is-hover {
    background-color: var(--hover);
}

.wh-section-head:active,
.wh-subsection-head:active,
.wh-section-head.is-active,
.wh-subsection-head.is-active {
    background-color: var(--press);
}

:is(.wh-section-head, .wh-subsection-head):is(:hover, :active, .is-hover, .is-active) > .wh-section-chevron {
    color: var(--ink);
}

.wh-section-head:focus-visible,
.wh-subsection-head:focus-visible,
.wh-section-head.is-focus,
.wh-subsection-head.is-focus {
    outline: 0;
    border-radius: var(--wh-r);
    box-shadow: var(--focus-ring);
}

/* Content: 16 px under the top-level line (10 px in Revit), 16 px before the next head */
.wh-section-body {
    padding: var(--wh-gap) 0;
}

.wh-subsection-head + .wh-fold > .wh-fold-inner > .wh-section-body {
    padding: var(--wh-gap-tight) 0 var(--wh-gap);
}


/* ── Fold: slides open by its grid row ────────────────────────── */
/* Closed: no height, hidden from the keyboard. Open: clips only while it moves (is-moving),
   so focus halos and pulled-out heads inside show once it has opened. */

.wh-fold {
    display: grid;
    grid-template-rows: 0fr;
    min-width: 0;
    transition: grid-template-rows var(--duration-open) var(--ease);
}

.wh-fold.is-open {
    grid-template-rows: 1fr;
}

.wh-fold > .wh-fold-inner {
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    visibility: hidden;
    transition: visibility 0s linear var(--duration-open);
}

.wh-fold.is-open > .wh-fold-inner {
    visibility: visible;
    transition-delay: 0s;
}

.wh-fold.is-open:not(.is-moving) > .wh-fold-inner {
    overflow: visible;
}

/* The section the user is working in: its label in red, like the current step */
.wh-section-head[aria-current="step"] > .wh-section-label {
    color: var(--red-text);
}


/* ── Tree ─────────────────────────────────────────────────────── */
/* Rows are full width: the chevron (right when closed, down when open), the tri-state checkbox
   when used, the label, a grey count, a status pill at the right. 24 px indent per level, with
   line-coloured guide lines running down from open parents under each parent's chevron.
   Rows are 32 px at 14 px on the web; in Revit they follow the size: 28 px at 13 px, 24 px at 12 px.
   Each label carries data-label, a bold copy that reserves the selected width.
   States: :hover / .is-hover, :active / .is-active, focus on the item / .is-focus,
   [aria-selected="true"] on the item / .is-selected on the row, [aria-expanded] on the item. */

.wh-tree {
    --wh-tree-h: min(var(--wh-h), var(--control-32));
    --wh-tree-fs: min(var(--wh-fs), 14px);
    --wh-tree-lh: min(var(--wh-lh), 20px);
    display: block;
    min-width: 0;
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--ink);
    font-size: var(--wh-tree-fs);
    line-height: var(--wh-tree-lh);
}

.wh-tree ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.wh-tree li {
    outline: 0;
}

.wh-tree [aria-expanded="false"] > ul {
    display: none;
}

.wh-tree-row {
    --wh-level: 0;
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    height: var(--wh-tree-h);
    min-width: 0;
    padding: 0 var(--wh-gap-tight) 0 calc(var(--wh-gap-tight) + var(--wh-level) * var(--space-indent));
    border-radius: var(--wh-r);
    background-color: transparent;
    background-image: repeating-linear-gradient(to right, transparent 0 7px, var(--line) 7px 8px, transparent 8px var(--space-indent));
    background-position: var(--wh-gap-tight) 0;
    background-size: calc(var(--wh-level) * var(--space-indent)) 100%;
    background-repeat: no-repeat;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-tree-row:hover,
.wh-tree-row.is-hover {
    background-color: var(--hover);
}

.wh-tree-row:active,
.wh-tree-row.is-active,
.wh-tree-row.is-selected,
[aria-selected="true"] > .wh-tree-row {
    background-color: var(--press);
}

.wh-tree-row.is-selected:hover,
.wh-tree-row.is-selected.is-hover,
.wh-tree-row.is-selected:active,
[aria-selected="true"] > .wh-tree-row:hover,
[aria-selected="true"] > .wh-tree-row:active {
    background-color: var(--press-deep);
}

.wh-tree-row.is-selected > .wh-tree-label,
[aria-selected="true"] > .wh-tree-row > .wh-tree-label {
    font-weight: 600;
}

[role="treeitem"]:focus-visible > .wh-tree-row,
.wh-tree-row.is-focus {
    box-shadow: var(--focus-ring);
}

/* Chevron: right when closed, down when open; its click area fills the row's height */
.wh-tree-toggle {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--icon);
    height: var(--icon);
    padding: 0;
    border: 0;
    background: none;
    color: var(--muted);
    cursor: pointer;
    transition: color var(--duration-fast) var(--ease);
}

.wh-tree-toggle::before {
    content: "";
    position: absolute;
    inset: calc((var(--icon) - var(--wh-tree-h)) / 2) calc(var(--wh-gap-tight) / -2);
}

.wh-tree-toggle > .wh-icon {
    transition: transform var(--duration-open) var(--ease);
}

[aria-expanded="true"] > .wh-tree-row > .wh-tree-toggle > .wh-icon {
    transform: rotate(90deg);
}

.wh-tree-row:hover > .wh-tree-toggle,
.wh-tree-row.is-hover > .wh-tree-toggle {
    color: var(--ink);
}

/* A leaf keeps the chevron's place, so labels line up */
.wh-tree-gap {
    flex: none;
    width: var(--icon);
}

.wh-tree-label {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The bold copy: as wide as the selected state, no height */
.wh-tree-label::after {
    content: attr(data-label);
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    font-weight: 600;
}

.wh-tree-count {
    flex: none;
    color: var(--muted);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The status pill (44-pill.css) keeps its size at the right; the label truncates first */
.wh-tree-row > .wh-pill {
    flex: none;
    margin-left: auto;
}


/* ── Table: a band header, 40 px rows, 14 px text ─────────────── */
/* Rows follow --wh-h: 40 px on the web, 28 px in Revit. Cells are 8 px in, so columns sit 16 px
   apart, and the outer cells keep the 16 px edge (5 and 10 px in Revit). Cells do not wrap.
   Clickable rows (a wh-table-link in the row): :hover / .is-hover, :active / .is-active,
   link :focus-visible / .is-focus. Edit table: 32 px inputs (24 px in Revit) whose text lines up
   with the headers; .has-issue on a row and a wh-table-issue row under it for its error. */

.wh-table-wrap {
    min-width: 0;
    overflow-x: auto;
    padding: 4px;
    margin: -4px;
}

.wh-table {
    --wh-row: var(--wh-h);
    --wh-cell: var(--wh-gap-tight);
    --wh-cell-edge: var(--wh-gap);
    /* The controls inside a row: one size down (32 px in a 40 px row, 24 px in a 28 px row) */
    --wh-in-h: var(--control-32);
    --wh-in-icon: var(--icon);
    --wh-in-fs: 14px;
    --wh-in-lh: 20px;
    --wh-in-fx: var(--space-tight);
    --wh-in-r: var(--radius-md);
    --wh-in-pad: calc((var(--wh-row) - var(--wh-in-h)) / 2);
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    color: var(--ink);
    font-size: min(var(--wh-fs), 14px);
    line-height: min(var(--wh-lh), 20px);
}

.wh-revit .wh-table {
    --wh-in-h: var(--control-24);
    --wh-in-icon: var(--icon-sm);
    --wh-in-fs: 12px;
    --wh-in-lh: 16px;
    --wh-in-fx: 6px;
    --wh-in-r: var(--radius-sm);
}

.wh-table th,
.wh-table td {
    height: var(--wh-row);
    padding: 0 var(--wh-cell);
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
    transition: background-color var(--duration-fast) var(--ease);
}

.wh-table th:first-child,
.wh-table td:first-child {
    padding-left: var(--wh-cell-edge);
}

.wh-table th:last-child,
.wh-table td:last-child {
    padding-right: var(--wh-cell-edge);
}

/* Header row: band grey, muted semibold labels at the field-label size */
.wh-table thead th {
    background: var(--band);
    color: var(--muted);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 600;
}

/* Numbers: right-aligned, tabular, with their unit */
.wh-table .wh-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}


/* ── Clickable rows: the row's link covers the whole row ───────── */

.wh-table tr:has(.wh-table-link) {
    position: relative;
    cursor: pointer;
}

.wh-table tr:has(.wh-table-link):hover > td,
.wh-table tr.is-hover > td {
    background: var(--hover);
}

.wh-table tr:has(.wh-table-link):active > td,
.wh-table tr.is-active > td {
    background: var(--press);
}

.wh-table-link {
    color: inherit;
    text-decoration: none;
    outline: 0;
}

.wh-table-link::after {
    content: "";
    position: absolute;
    inset: 0;
    outline: 1px solid transparent;
    outline-offset: -1px;
    transition: box-shadow var(--duration-fast) var(--ease), outline-color var(--duration-fast) var(--ease);
}

.wh-table-link:focus-visible::after,
.wh-table tr.is-focus .wh-table-link::after {
    outline-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

/* Controls in a clickable row stay above the link */
.wh-table tr:has(.wh-table-link) :is(button, input, select, textarea, a:not(.wh-table-link)) {
    position: relative;
    z-index: 1;
}


/* ── Controls in cells: edit tables and the action cell ───────── */

.wh-table-edit td,
.wh-table .wh-table-action {
    --wh-h: var(--wh-in-h);
    --wh-icon: var(--wh-in-icon);
    --wh-fs: var(--wh-in-fs);
    --wh-lh: var(--wh-in-lh);
    --wh-fx: var(--wh-in-fx);
    --wh-r: var(--wh-in-r);
}

/* Inputs fill their cell, 8 px apart; the first input's text sits on the 16 px edge */
.wh-table-edit td {
    padding: 0 var(--wh-in-pad);
}

.wh-table-edit td:first-child {
    padding-left: calc(var(--wh-cell-edge) - var(--wh-in-fx) - 1px);
}

.wh-table-edit td:last-child {
    padding-right: calc(var(--wh-cell-edge) - var(--wh-in-fx) - 1px);
}

.wh-table-edit .wh-field {
    width: 100%;
}

/* Plain text in an edit table sits on the header's line */
.wh-table-edit td:not(:has(.wh-field, .wh-icon-btn)) {
    padding: 0 calc(var(--wh-in-pad) + 1px + var(--wh-in-fx));
}

.wh-table-edit td:first-child:not(:has(.wh-field, .wh-icon-btn)) {
    padding-left: var(--wh-cell-edge);
}

.wh-table-edit td:last-child:not(:has(.wh-field, .wh-icon-btn)) {
    padding-right: var(--wh-cell-edge);
}

/* Headers start where the input text starts */
.wh-table-edit th {
    padding: 0 calc(var(--wh-in-pad) + 1px + var(--wh-in-fx));
}

.wh-table-edit th:first-child {
    padding-left: var(--wh-cell-edge);
}

.wh-table-edit th:last-child {
    padding-right: var(--wh-cell-edge);
}

/* Action cell: a 32 px icon button (24 px in Revit) whose icon sits on the edge */
.wh-table .wh-table-action {
    width: 1%;
    padding: 0 var(--wh-cell);
    text-align: right;
}

.wh-table .wh-table-action:last-child {
    padding-right: calc(var(--wh-cell-edge) - (var(--wh-in-h) - var(--wh-in-icon)) / 2);
}

.wh-table-action > .wh-icon-btn {
    vertical-align: middle;
}

/* A row's error: plain red text under the row, on the line of the first input's text */
.wh-table tr.has-issue > td {
    border-bottom: 0;
}

.wh-table .wh-table-issue > td {
    height: auto;
    padding: calc(var(--wh-gap-tight) - var(--wh-in-pad)) var(--wh-cell-edge) var(--wh-gap-tight);
    color: var(--red-text);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    white-space: normal;
}


/* ── In a bordered box: the box's border closes the table ─────── */
/* A table that ends a card or a framed box leaves its last line to the box's border, so no two
   lines meet. Where the table runs to the box's edges (wh-card-flush, a flush dialog body) the box
   clips, so a clickable row draws its focus halo inside the row, where nothing cuts it off. */

:is(.wh-card, .wh-demo-box) > :is(.wh-table-wrap, .wh-table):last-child tbody tr:last-child > td {
    border-bottom: 0;
}

:is(.wh-card-flush, .wh-dialog-body.is-flush) .wh-table-link::before {
    content: "";
    position: absolute;
    inset: var(--space-hair);
    border-radius: var(--wh-r);
    pointer-events: none;
    transition: box-shadow var(--duration-fast) var(--ease);
}

:is(.wh-card-flush, .wh-dialog-body.is-flush) .wh-table-link:focus-visible::after,
:is(.wh-card-flush, .wh-dialog-body.is-flush) .wh-table tr.is-focus .wh-table-link::after {
    outline-color: transparent;
    box-shadow: none;
}

:is(.wh-card-flush, .wh-dialog-body.is-flush) .wh-table-link:focus-visible::before,
:is(.wh-card-flush, .wh-dialog-body.is-flush) .wh-table tr.is-focus .wh-table-link::before {
    box-shadow: 0 0 0 1px var(--edge-hover), var(--focus-ring);
}


/* ── Pill: status only ────────────────────────────────────────── */
/* 24 px high (20 px in Revit), 12 px semibold, radius-pill, 8 px sides. Not interactive, so no states.
   Neutral by default: ink at 10 % over its ground, the press grey on surface, and still a step
   darker on a hovered or pressed row or tile; wh-pill-strong (ink fill, on-ink), wh-pill-red (red fill,
   on-red), wh-pill-weak (edge outline, muted). A cut label ends in an ellipsis. */

.wh-pill {
    --wh-pill-h: var(--control-24);
    display: inline-block;
    min-width: 0;
    max-width: 100%;
    height: var(--wh-pill-h);
    padding: 0 var(--space-tight);
    overflow: hidden;
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--ink) 10%, transparent);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 12px;
    line-height: calc(var(--wh-pill-h) - 2px);
    font-weight: 600;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

.wh-revit .wh-pill {
    --wh-pill-h: calc(var(--control-24) - var(--space-hair));
}

.wh-pill-strong {
    background: var(--ink);
    color: var(--on-ink);
}

.wh-pill-red {
    background: var(--red);
    color: var(--on-red);
}

.wh-pill-weak {
    border-color: var(--edge);
    background: transparent;
    color: var(--muted);
}


/* ── Option tile: one calculated option to choose (I-Block) ───── */
/* Top row: code (12 px mono, muted), name (14 px semibold), rating pill. Then the yield, the one
   24 px bold number, and the figures: 12 px muted labels over 14 px regular values (type variant C).
   Chosen = a dark ink ring, drawn as an inset outline so nothing moves.
   States: :hover / .is-hover, :active / .is-active, :focus-visible / .is-focus,
   aria-checked="true" / .is-selected. */

.wh-options {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--wh-gap);
}

@media (max-width: 767.98px) {
    .wh-options {
        grid-template-columns: minmax(0, 1fr);
    }
}

.wh-option {
    display: flex;
    flex-direction: column;
    gap: var(--wh-gap-tight);
    width: 100%;
    min-width: 0;
    margin: 0;
    padding: var(--wh-gap);
    border: 1px solid var(--line);
    border-radius: var(--wh-r-lg);
    outline: 1px solid transparent;
    outline-offset: -2px;
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 20px;
    font-weight: 400;
    text-align: left;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), outline-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.wh-option:hover,
.wh-option.is-hover {
    border-color: var(--edge-hover);
    background: var(--hover);
}

.wh-option:active,
.wh-option.is-active {
    border-color: var(--edge-hover);
    background: var(--press);
}

.wh-option:focus-visible,
.wh-option.is-focus {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-option[aria-checked="true"],
.wh-option.is-selected {
    border-color: var(--ink);
    outline-color: var(--ink);
}

/* Top row: the name takes the room left and ends in an ellipsis first */
.wh-option-top {
    display: flex;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
}

.wh-option-code {
    flex: none;
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 16px;
}

.wh-option-name {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Body: the yield on the left, the figures on the right, on one baseline; they wrap when narrow */
.wh-option-body {
    display: flex;
    flex-wrap: wrap;
    align-items: last baseline;
    justify-content: space-between;
    gap: var(--wh-gap-tight) var(--wh-gap);
    min-width: 0;
}

.wh-option-yield {
    display: flex;
    align-items: baseline;
    gap: var(--wh-gap-tight);
    white-space: nowrap;
}

.wh-option-yield > strong {
    font-size: 24px;
    line-height: 30px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.wh-option-yield > span {
    color: var(--muted);
    font-size: 12px;
    line-height: 16px;
}

/* Figures: label over value; a row of text items, 16 px apart */
.wh-figures {
    display: flex;
    flex-wrap: wrap;
    gap: var(--wh-gap-tight) var(--wh-gap);
    min-width: 0;
}

.wh-figure {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.wh-figure-label {
    color: var(--muted);
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
}

.wh-figure-value {
    font-size: 14px;
    line-height: 20px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}


/* ── Details: read-only labels over their values ──────────────── */
/* A <dl> whose items are <div>s, each a muted semibold label (dt, 14 px; 12 px in Revit) 8 px
   above its value (dd, 14 px; 13 px in Revit, 5 px under its label). The items fill a grid of columns at
   least 160 px wide (128 px in Revit) that wraps with the room, 16 px apart both ways (10 px in
   Revit). Units stay with their values in unit grey. wh-details-group stacks several lists, each
   under a 16 px semibold head (14 px in Revit); their columns line up because they share a width.
   A dl without item <div>s still reads: one column, each label over its value. */

:root {
    --wh-details-head-fs: 16px;
    --wh-details-head-lh: 24px;
    --wh-details-col: 10rem;
}

.wh-revit {
    --wh-details-head-fs: 14px;
    --wh-details-head-lh: 20px;
    --wh-details-col: 8rem;
}

.wh-details {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--wh-details-col)), 1fr));
    align-items: start;
    gap: var(--wh-gap);
    margin: 0;
    color: var(--ink);
    font-size: min(var(--wh-fs), 14px);
    line-height: min(var(--wh-lh), 20px);
}

.wh-details > div {
    display: flex;
    flex-direction: column;
    gap: var(--wh-gap-tight);
    min-width: 0;
}

.wh-details dt {
    min-width: 0;
    overflow: hidden;
    color: var(--muted);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-details dd {
    min-width: 0;
    margin: 0;
    overflow-wrap: anywhere;
}

.wh-details .wh-num {
    font-variant-numeric: tabular-nums;
}

/* Items written straight into the dl: one column, each label over its value */
.wh-details:not(:has(> div)) {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
}

.wh-details:not(:has(> div)) > dt {
    margin-bottom: var(--wh-gap-tight);
}

.wh-details:not(:has(> div)) > dd + dt {
    margin-top: var(--wh-gap);
}

/* Several lists under their heads; the lists share the group's width, so their columns line up */
.wh-details-group {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--wh-gap);
    align-content: start;
}

.wh-details-head {
    margin: 0 0 calc(var(--wh-gap-tight) - var(--wh-gap));
    color: var(--ink);
    font-size: var(--wh-details-head-fs);
    line-height: var(--wh-details-head-lh);
    font-weight: 600;
}


/* ── Tooltip: the Würth tooltip, never the browser's title ───── */
/* An ink label, on-ink 12 px semibold text, radius-sm, a 4 px arrow, shadow-menu. It sits 8 px
   from its target, so the arrow tip is 4 px away. W.tooltips places one shared .wh-tooltip after a
   500 ms pause or at once on keyboard focus.
   Placement: .is-top (default), .is-bottom, .is-left, .is-right — the side of the target it sits on.
   --wh-tip-arrow moves the arrow along the edge when the label is held inside the window.
   States: .is-open (shown). */

:root {
    --wh-tip-gap: var(--space-tight);
    --wh-tip-arrow-size: var(--space-hair);
    --wh-tip-max: var(--tooltip-max);
}

.wh-tooltip {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1100;
    box-sizing: border-box;
    width: max-content;
    max-width: min(var(--wh-tip-max), calc(100vw - 2 * var(--space-tight)));
    padding: var(--space-hair) var(--space-tight);
    border-radius: var(--radius-sm);
    background: var(--ink);
    box-shadow: var(--shadow-menu);
    color: var(--on-ink);
    font-family: var(--font-sans);
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-align: left;
    white-space: normal;
    overflow-wrap: break-word;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transform: translateY(2px);
    transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease), visibility 0s linear var(--duration-fast);
}

.wh-tooltip.is-bottom {
    transform: translateY(-2px);
}

.wh-tooltip.is-left {
    transform: translateX(2px);
}

.wh-tooltip.is-right {
    transform: translateX(-2px);
}

.wh-tooltip.is-open {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease), visibility 0s;
}

/* The arrow: a border triangle in the label's fill, pointing at the target */
.wh-tooltip::after {
    content: "";
    position: absolute;
    border: var(--wh-tip-arrow-size) solid transparent;
}

.wh-tooltip::after,
.wh-tooltip.is-top::after {
    top: 100%;
    left: var(--wh-tip-arrow, 50%);
    margin-left: calc(var(--wh-tip-arrow-size) * -1);
    border-top-color: var(--ink);
}

.wh-tooltip.is-bottom::after {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--ink);
}

.wh-tooltip.is-left::after,
.wh-tooltip.is-right::after {
    top: var(--wh-tip-arrow, 50%);
    margin-left: 0;
    margin-top: calc(var(--wh-tip-arrow-size) * -1);
    border-top-color: transparent;
}

.wh-tooltip.is-left::after {
    left: 100%;
    border-left-color: var(--ink);
}

.wh-tooltip.is-right::after {
    left: auto;
    right: 100%;
    border-right-color: var(--ink);
}

/* Cut text: one line that ends in an ellipsis; the tooltip shows the whole of it */
.wh-cut {
    display: block;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* ── Spec sheets only: a tooltip drawn beside its target ──────── */
/* .wh-demo-tip lays a static .wh-tooltip out beside its target with the 8 px gap, in source order
   (column for top and bottom, row with .is-row for left and right). .is-reserved keeps a label's
   room while it is hidden, so targets line up across a sheet row. */

.wh-demo-tip {
    display: inline-grid;
    justify-items: center;
    align-items: center;
    gap: var(--wh-tip-gap);
}

.wh-demo-tip.is-row {
    grid-auto-flow: column;
}

.wh-demo-tip > .wh-tooltip {
    position: relative;
    z-index: auto;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
}

.wh-demo-tip > .wh-tooltip.is-reserved {
    visibility: hidden;
}


/* ── Dialog: raised, over a scrim ─────────────────────────────── */
/* raised, 1 px line border, radius-lg (radius-md in Revit), shadow-dialog. Head 56 px with the
   20 px semibold title and an x-lg icon button (44 px and 14 px in Revit). The body has 16 px
   padding and scrolls under overlay bars. The footer sits on band with a line on top: Cancel, then
   the primary action, on the right, both button-min wide.
   Widths: 32 rem, .wh-dialog-wide 64 rem; never wider than the window less its edges.
   .wh-dialog-scrim covers the page; .is-open fades it in and the dialog rises 8 px over
   duration-open. Outside a scrim a .wh-dialog draws in place (spec sheets). */

:root {
    --wh-dialog-w: var(--dialog);
    --wh-dialog-head: var(--header);
    --wh-dialog-title-fs: 20px;
    --wh-dialog-title-lh: 28px;
}

.wh-revit {
    --wh-dialog-head: var(--upper-bar);
    --wh-dialog-title-fs: 14px;
    --wh-dialog-title-lh: 20px;
}

.wh-dialog-scrim {
    position: fixed;
    inset: 0;
    z-index: 1078;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--wh-gap);
    background: var(--scrim);
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease);
}

.wh-dialog-scrim[hidden] {
    display: none;
}

.wh-dialog-scrim.is-open {
    opacity: 1;
}

.wh-dialog {
    display: flex;
    flex-direction: column;
    width: min(var(--wh-dialog-w), 100%);
    min-width: 0;
    max-width: 100%;
    max-height: 100%;
    border: 1px solid var(--line);
    border-radius: var(--wh-r-lg);
    background: var(--raised);
    box-shadow: var(--shadow-dialog);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--wh-fs);
    line-height: var(--wh-lh);
    text-align: left;
}

.wh-dialog-wide {
    --wh-dialog-w: var(--dialog-wide);
}

.wh-dialog-scrim > .wh-dialog {
    transform: translateY(var(--space-tight));
    transition: transform var(--duration-open) var(--ease);
}

.wh-dialog-scrim.is-open > .wh-dialog {
    transform: none;
}

.wh-dialog:focus {
    outline: 0;
}

/* Head: the title at the content edge, the close button in a square inset */
.wh-dialog-head {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--wh-gap-tight);
    min-width: 0;
    min-height: var(--wh-dialog-head);
    padding: 0 calc((var(--wh-dialog-head) - min(var(--wh-h), var(--control-32))) / 2) 0 var(--wh-gap);
    border-bottom: 1px solid var(--line);
}

.wh-dialog-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    color: var(--ink);
    font-size: var(--wh-dialog-title-fs);
    line-height: var(--wh-dialog-title-lh);
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-dialog-head > .wh-icon-btn {
    margin-left: auto;
}

/* Body: scrolls on its own between the head and the footer */
.wh-dialog-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--wh-gap);
}

/* Flush: a table runs edge to edge; its outer cells keep the 16 px edge. The header row stays
   while the rows scroll, and the last row leaves its line to the footer's */
.wh-dialog-body.is-flush {
    padding: 0;
}

.wh-dialog-body.is-flush .wh-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
}

.wh-dialog-body.is-flush .wh-table tbody tr:last-child > td {
    border-bottom: 0;
}

.wh-dialog-body > :first-child {
    margin-top: 0;
}

.wh-dialog-body > :last-child {
    margin-bottom: 0;
}

/* Footer: band, a line on top, the buttons at the right */
.wh-dialog-foot {
    display: flex;
    flex: none;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--wh-gap-tight);
    min-width: 0;
    padding: var(--wh-gap);
    border-top: 1px solid var(--line);
    border-radius: 0 0 calc(var(--wh-r-lg) - 1px) calc(var(--wh-r-lg) - 1px);
    background: var(--band);
}

.wh-dialog-foot .wh-btn {
    min-width: var(--button-min);
}

/* No head line when the body is empty: the footer's line is enough */
.wh-dialog-head:has(+ .wh-dialog-foot) {
    border-bottom: 0;
}

@media (max-width: 575.98px) {
    .wh-dialog-foot > .wh-btn {
        flex: 1 1 var(--button-min);
    }
}

/* The page does not scroll behind an open dialog */
.wh-has-dialog {
    overflow: hidden;
}


/* ── Spec sheets only (wh-demo-*) ─────────────────────────────── */
/* .wh-demo-screen: a framed piece of window that holds a page, and an open scrim and dialog in place.
   .wh-demo-page: the page behind it. .wh-demo-box / .wh-demo-scroll / .wh-demo-list: framed scroll
   boxes for the Scrollbar sheets. .wh-demo-bars-on: overlay bars inside are drawn as while scrolling. */

.wh-demo-screen {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
}

.wh-demo-screen > .wh-dialog-scrim {
    position: absolute;
}

.wh-demo-page {
    display: grid;
    align-content: start;
    gap: var(--wh-gap);
    color: var(--ink);
}

.wh-demo-page-head {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: var(--wh-gap);
    height: var(--header);
    padding: 0 var(--wh-gap);
    border-bottom: 2px solid var(--red);
    background: var(--surface);
    font-weight: 600;
}

.wh-demo-page-head > span + span {
    color: var(--muted);
    font-size: 14px;
    font-weight: 400;
}

.wh-demo-page-body {
    display: grid;
    gap: var(--wh-gap);
    padding: 0 var(--wh-gap) var(--wh-gap);
}

.wh-demo-scroll .wh-table tbody tr:last-child > td {
    border-bottom: 0;
}

/* A framed scroll box and its list rows, for the Scrollbar sheets. The frame holds the border, so
   the edge fade of a horizontal scroller never fades the border with it */
.wh-demo-box {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
    color: var(--ink);
}

.wh-demo-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    outline: 0;
}

.wh-demo-box:has(> .wh-demo-scroll:focus-visible) {
    border-color: var(--edge-hover);
    box-shadow: var(--focus-ring);
}

.wh-demo-list > div {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-tight);
    height: var(--control-32);
    padding: 0 var(--space);
    border-bottom: 1px solid var(--line);
    font-size: 14px;
    line-height: 20px;
    white-space: nowrap;
}

.wh-demo-list > div:last-child {
    border-bottom: 0;
}

.wh-demo-list > div > span:last-child {
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.wh-demo-bars-on .wh-bar-track.is-v,
.wh-demo-bars-on .wh-bar-track.is-h {
    opacity: 1;
}


/* ── Warnings: plain red lines ────────────────────────────────── */
/* One line per warning in red-text, at the error size (14 px on the web, 12 px in Revit), 4 px
   apart. No icons, no boxes, no bullets. A long line wraps under itself. */

.wh-warnings {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-hair);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--red-text);
    font-family: var(--font-sans);
    font-size: var(--wh-label-fs);
    line-height: var(--wh-label-lh);
    font-weight: 400;
}

.wh-warnings > li {
    min-width: 0;
    margin: 0;
    overflow-wrap: break-word;
}
