/* Shared field interaction contract: Register + Settings.
   One state machine for NORMAL -> HOVER -> PRIMARY -> DISABLED.
   Page-specific CSS owns geometry/layout only; interaction state lives here. */

body.register-control-contract-page :is(.index, .config-page),
#themeColorPicker {
    --control-state-normal: var(--control-border);
    --control-state-hover: var(--control-hover-border);
    --control-state-primary: var(--primary);
    --control-state-disabled: var(--control-border);
    --control-state-accent: var(--control-state-normal);
    --control-icon-normal: color-mix(in srgb, var(--control-text) 62%, transparent);
}

/* STATE 1/4: NORMAL */
body.register-control-contract-page :is(.index, .config-page) :where(
    input.config-input:not([type="number"]),
    input.file-config-input:not([type="number"]):not([type="file"]):not(.config-secret-input),
    .file-content-textarea,
    .custom-select-search input,
    .number-input-wrapper,
    .custom-select,
    .config-native-select,
    .settings-native-select,
    .items-per-page-custom,
    input.file-config-input[type="file"],
    .password-input-wrapper,
    .file-upload-container,
    select.items-per-page-select,
    button.control-surface,
    .page-info.control-surface
),
#themeColorPicker .theme-color-hex-input {
    --control-state-accent: var(--control-state-normal);
    --control-icon-color: var(--control-icon-normal);
}

/* STATE 2/4: HOVER */
body.register-control-contract-page :is(.index, .config-page) :where(
    input.config-input:not([type="number"]):not(:disabled):hover,
    input.file-config-input:not([type="number"]):not([type="file"]):not(.config-secret-input):not(:disabled):hover,
    .file-content-textarea:not(:disabled):hover,
    .custom-select-search input:not(:disabled):hover,
    .number-input-wrapper:not(:has(:disabled)):hover,
    .custom-select:not(.active):not(:has(> .custom-select-trigger:disabled)):not(:has(> .custom-select-trigger[aria-disabled="true"])):has(> .custom-select-trigger:hover),
    .config-native-select:not(.open):not(:has(> .config-native-select-trigger:disabled)):not(:has(> .config-native-select-trigger[aria-disabled="true"])):has(> .config-native-select-trigger:hover),
    .settings-native-select:not(.open):not(:has(> .settings-native-select-trigger:disabled)):not(:has(> .settings-native-select-trigger[aria-disabled="true"])):has(> .settings-native-select-trigger:hover),
    .items-per-page-custom:not(.open):not(:has(> .items-per-page-custom-trigger:disabled)):not(:has(> .items-per-page-custom-trigger[aria-disabled="true"])):has(> .items-per-page-custom-trigger:hover),
    input.file-config-input[type="file"]:not(:disabled):hover,
    .password-input-wrapper:not(:has(> .file-config-input:disabled)):hover,
    .file-upload-container:not(:has(:disabled)):hover,
    select.items-per-page-select:not(:disabled):hover,
    button.control-surface:not(:disabled):hover,
    .page-info.control-surface:hover
),
#themeColorPicker .theme-color-hex-input:not(:disabled):hover {
    --control-state-accent: var(--control-state-hover);
    --control-icon-color: var(--control-state-hover);
}

/* STATE 3/4: PRIMARY.
   This deliberately mirrors the Register-page contract:
   text/number fields stay primary while focused; dropdown pointer-focus alone
   does not create a stale primary state after a closed dropdown. */
body.register-control-contract-page :is(.index, .config-page) :where(
    input.config-input:not([type="number"]):not(:disabled):is(:focus, :focus-visible),
    input.file-config-input:not([type="number"]):not([type="file"]):not(.config-secret-input):not(:disabled):is(:focus, :focus-visible),
    .file-content-textarea:not(:disabled):is(:focus, :focus-visible),
    .custom-select-search input:not(:disabled):is(:focus, :focus-visible),
    .number-input-wrapper:not(:has(:disabled)):focus-within,
    .number-input-wrapper:not(:has(:disabled)):has(.custom-spinner-btn:active),
    .custom-select:has(> .custom-select-trigger:active),
    .config-native-select:has(> .config-native-select-trigger:active),
    .settings-native-select:has(> .settings-native-select-trigger:active),
    .items-per-page-custom:has(> .items-per-page-custom-trigger:active),
    .custom-select:has(> .custom-select-trigger:focus-visible),
    .config-native-select:has(> .config-native-select-trigger:focus-visible),
    .settings-native-select:has(> .settings-native-select-trigger:focus-visible),
    .items-per-page-custom:has(> .items-per-page-custom-trigger:focus-visible),
    .custom-select.active,
    .config-native-select.open,
    .settings-native-select.open,
    .items-per-page-custom.open,
    input.file-config-input[type="file"]:not(:disabled):is(:focus, :focus-visible, :active),
    .password-input-wrapper:focus-within,
    .file-upload-container:has(> :is(input.file-config-input, textarea.file-content-textarea):is(:focus, :focus-visible)),
    .file-upload-container:has(.btn-upload-inline:active),
    .file-upload-container:has(.btn-upload-inline:focus-visible),
    select.items-per-page-select:not(:disabled):is(:focus-visible, :active, :open),
    button.control-surface:not(:disabled):is(:active, :focus-visible),
    .page-info.control-surface:is(:active, :focus-visible),
    .page-info.control-surface.page-selector-open
),
#themeColorPicker .theme-color-hex-input:not(:disabled):is(:focus, :focus-visible) {
    --control-state-accent: var(--control-state-primary);
    --control-icon-color: var(--control-state-primary);
}

/* STATE 4/4: DISABLED wins by source order. */
body.register-control-contract-page :is(.index, .config-page) :where(
    input.config-input:disabled,
    input.file-config-input:disabled,
    .file-content-textarea:disabled,
    .custom-select-search input:disabled,
    .number-input-wrapper:has(:disabled),
    .custom-select:has(> .custom-select-trigger:disabled),
    .config-native-select:has(> .config-native-select-trigger:disabled),
    .settings-native-select:has(> .settings-native-select-trigger:disabled),
    .items-per-page-custom:has(> .items-per-page-custom-trigger:disabled),
    .custom-select:has(> .custom-select-trigger[aria-disabled="true"]),
    .config-native-select:has(> .config-native-select-trigger[aria-disabled="true"]),
    .settings-native-select:has(> .settings-native-select-trigger[aria-disabled="true"]),
    .items-per-page-custom:has(> .items-per-page-custom-trigger[aria-disabled="true"]),
    .password-input-wrapper:has(> .file-config-input:disabled),
    .file-upload-container:has(:disabled),
    select.items-per-page-select:disabled,
    button.control-surface:disabled
),
#themeColorPicker .theme-color-hex-input:disabled {
    --control-state-accent: var(--control-state-disabled);
    --control-icon-color: var(--control-state-disabled);
}

/* Every visible field consumes the same accent. */
body.register-control-contract-page :is(.index, .config-page) :where(
    input.config-input,
    input.file-config-input:not([type="file"]),
    .file-content-textarea,
    .custom-select-search input,
    select.items-per-page-select,
    .custom-select-trigger,
    .config-native-select-trigger,
    .settings-native-select-trigger,
    .items-per-page-custom-trigger
),
#themeColorPicker .theme-color-hex-input {
    border-color: var(--control-state-accent) !important;
    background-color: var(--control-bg) !important;
    color: var(--control-text) !important;
    box-shadow: none !important;
    outline: none !important;
}

/* Number inputs and spinner arrows consume the wrapper state. */
body.register-control-contract-page :is(.index, .config-page) .number-input-wrapper > :where(.config-input, .file-config-input) {
    --control-state-accent: inherit;
    border-color: var(--control-state-accent) !important;
}

body.register-control-contract-page :is(.index, .config-page) .custom-spinner-btn {
    background: transparent !important;
    background-color: transparent !important;
    color: var(--control-icon-color, var(--control-state-accent)) !important;
    border: 0 !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) .custom-spinner-btn > svg {
    fill: none !important;
    stroke: currentColor !important;
}

/* Every dropdown chevron uses exactly the same accent as its trigger border. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select-trigger > svg,
    .config-native-select-trigger > .dropdown-trigger-arrow,
    .settings-native-select-trigger > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger > .dropdown-trigger-arrow
) {
    color: var(--control-icon-color, var(--control-state-accent)) !important;
    stroke: currentColor !important;
}

/* Canonical joined open frame: trigger + menu are one continuous Primary outline. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select.active .custom-select-trigger,
    .config-native-select.open .config-native-select-trigger,
    .settings-native-select.open .settings-native-select-trigger,
    .items-per-page-custom.open .items-per-page-custom-trigger
) {
    border: 1px solid var(--control-state-accent) !important;
    border-bottom: 1px solid var(--control-state-accent) !important;
    border-radius: var(--form-control-radius) var(--form-control-radius) 0 0 !important;
    box-sizing: border-box !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select.active .custom-select-options.show,
    .config-native-select.open .config-native-select-menu,
    .settings-native-select.open .settings-native-select-menu,
    .items-per-page-custom.open .items-per-page-custom-menu
) {
    top: 100% !important;
    left: 0 !important;
    right: 0 !important;
    width: auto !important;
    margin-top: 0 !important;
    border-top: 0 !important;
    border-left: 1px solid var(--control-state-accent) !important;
    border-right: 1px solid var(--control-state-accent) !important;
    border-bottom: 1px solid var(--control-state-accent) !important;
    border-radius: 0 0 var(--form-control-radius) var(--form-control-radius) !important;
    box-sizing: border-box !important;
    box-shadow: none !important;
    outline: none !important;
}

/* Every open dropdown popup uses the same primary frame and popup surface. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select.active .custom-select-options.show,
    .config-native-select.open .config-native-select-menu,
    .settings-native-select.open .settings-native-select-menu,
    .items-per-page-custom.open .items-per-page-custom-menu
) {
    background: var(--dropdown-control-surface) !important;
    background-color: var(--dropdown-control-surface) !important;
    border-left-color: var(--control-state-accent) !important;
    border-right-color: var(--control-state-accent) !important;
    border-bottom-color: var(--control-state-accent) !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) .custom-select.active .custom-select-options.show .custom-select-search {
    background: var(--dropdown-control-surface) !important;
    background-color: var(--dropdown-control-surface) !important;
}

/* Password composite follows the same accent. */
body.register-control-contract-page :is(.index, .config-page) .password-input-wrapper > .file-config-input {
    --control-state-accent: inherit;
    border-color: var(--control-state-accent) !important;
}

body.register-control-contract-page :is(.index, .config-page) .password-toggle-btn {
    background: transparent !important;
    background-color: transparent !important;
    color: var(--control-icon-color, var(--control-state-accent)) !important;
    border: 0 !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) .password-toggle-btn > .eye-icon {
    color: inherit !important;
    stroke: currentColor !important;
}

/* Compact action icons use the same visual language everywhere.
   Trigger-level actions inherit their parent control state; popup copy actions
   stay neutral until the user interacts with that action itself. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .server-url-copy-btn-trigger
) {
    background: transparent !important;
    background-color: transparent !important;
    color: var(--control-icon-color, var(--control-icon-normal)) !important;
    border-color: transparent !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) :where(
    .server-url-copy-btn
) {
    background: transparent !important;
    background-color: transparent !important;
    color: var(--control-icon-normal) !important;
    border-color: transparent !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) .server-url-copy-btn:is(:hover, :active, :focus, :focus-visible) {
    color: var(--control-state-primary) !important;
    background: transparent !important;
    background-color: transparent !important;
    box-shadow: none !important;
    outline: none !important;
}

body.register-control-contract-page :is(.index, .config-page) :where(
    .server-url-copy-btn-trigger > svg,
    .server-url-copy-btn > svg
) {
    color: inherit !important;
    stroke: currentColor !important;
    fill: none !important;
}

/* Keep disabled cursors consistent. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select-trigger:disabled,
    .config-native-select-trigger:disabled,
    .settings-native-select-trigger:disabled,
    .items-per-page-custom-trigger:disabled,
    .custom-select-trigger[aria-disabled="true"],
    .config-native-select-trigger[aria-disabled="true"],
    .settings-native-select-trigger[aria-disabled="true"],
    .items-per-page-custom-trigger[aria-disabled="true"]
) {
    cursor: not-allowed;
}

/* Shared control icon geometry: dropdown + NumberUpDown use one size and one right-edge anchor. */
body.register-control-contract-page :is(.index, .config-page) {
    --control-chevron-size: 12px;
    --control-chevron-right: 0.75rem;
    --control-spinner-button-width: 12px;
    --control-spinner-button-height: 12px;
    --control-spinner-gap: 1px;
    --control-icon-zone-width: calc(var(--control-chevron-right) + var(--control-spinner-button-width));
}

/* Dropdown trigger and NumberUpDown reserve the same right-side icon zone. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select-trigger,
    .config-native-select-trigger,
    .settings-native-select-trigger,
    .items-per-page-custom-trigger
) {
    position: relative !important;
    padding-right: calc(var(--control-icon-zone-width) + 0.5rem) !important;
}

body.register-control-contract-page :is(.index, .config-page) .number-input-wrapper > :where(.config-input, .file-config-input) {
    padding-right: calc(var(--control-icon-zone-width) + 0.5rem) !important;
}

/* Every dropdown chevron has the same 12x12 geometry and right-edge offset. */
body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select-trigger > svg,
    .config-native-select-trigger > .dropdown-trigger-arrow,
    .settings-native-select-trigger > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger > .dropdown-trigger-arrow
) {
    position: absolute !important;
    top: 50% !important;
    right: var(--control-chevron-right) !important;
    width: var(--control-chevron-size) !important;
    height: var(--control-chevron-size) !important;
    min-width: var(--control-chevron-size) !important;
    min-height: var(--control-chevron-size) !important;
    margin: 0 !important;
    flex: 0 0 var(--control-chevron-size) !important;
    transform: translateY(-50%) rotate(0deg) !important;
    transform-origin: center !important;
    stroke-width: 1.7 !important;
    stroke-linecap: round !important;
    stroke-linejoin: round !important;
}

body.register-control-contract-page :is(.index, .config-page) :where(
    .custom-select.active .custom-select-trigger > svg,
    .config-native-select.open .config-native-select-trigger > .dropdown-trigger-arrow,
    .settings-native-select.open .settings-native-select-trigger > .dropdown-trigger-arrow,
    .items-per-page-custom.open .items-per-page-custom-trigger > .dropdown-trigger-arrow
) {
    transform: translateY(-50%) rotate(180deg) !important;
}

/* NumberUpDown uses the exact same right-edge anchor and 12px chevrons. */
body.register-control-contract-page :is(.index, .config-page) .custom-spinner-buttons {
    position: absolute !important;
    top: 50% !important;
    right: var(--control-chevron-right) !important;
    bottom: auto !important;
    width: var(--control-spinner-button-width) !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    gap: var(--control-spinner-gap) !important;
    transform: translateY(-50%) !important;
    pointer-events: none !important;
}

body.register-control-contract-page :is(.index, .config-page) .custom-spinner-btn {
    width: var(--control-spinner-button-width) !important;
    height: var(--control-spinner-button-height) !important;
    min-width: var(--control-spinner-button-width) !important;
    min-height: var(--control-spinner-button-height) !important;
    padding: 0 !important;
    margin: 0 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    pointer-events: auto !important;
    background: transparent !important;
    background-color: transparent !important;
}

body.register-control-contract-page :is(.index, .config-page) .custom-spinner-btn > svg {
    width: var(--control-chevron-size) !important;
    height: var(--control-chevron-size) !important;
    min-width: var(--control-chevron-size) !important;
    min-height: var(--control-chevron-size) !important;
    stroke-width: 1.7 !important;
    stroke-linecap: round !important;
    stroke-linejoin: round !important;
}

/* OPEN/CLICK dropdown chevrons are explicitly Primary.
   Pin both the SVG and its rendered stroke nodes so active/open state cannot
   lose Primary through SVG inheritance or page-specific cascade rules. */
body.register-control-contract-page :is(.index, .config-page) :is(
    .custom-select-trigger:active > svg,
    .config-native-select-trigger:active > .dropdown-trigger-arrow,
    .settings-native-select-trigger:active > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger:active > .dropdown-trigger-arrow,
    .custom-select.active .custom-select-trigger > svg,
    .config-native-select.open .config-native-select-trigger > .dropdown-trigger-arrow,
    .settings-native-select.open .settings-native-select-trigger > .dropdown-trigger-arrow,
    .items-per-page-custom.open .items-per-page-custom-trigger > .dropdown-trigger-arrow,
    .custom-select-trigger[aria-expanded="true"] > svg,
    .config-native-select-trigger[aria-expanded="true"] > .dropdown-trigger-arrow,
    .settings-native-select-trigger[aria-expanded="true"] > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger[aria-expanded="true"] > .dropdown-trigger-arrow
) {
    color: var(--control-state-primary) !important;
    stroke: var(--control-state-primary) !important;
}

body.register-control-contract-page :is(.index, .config-page) :is(
    .custom-select-trigger:active > svg,
    .config-native-select-trigger:active > .dropdown-trigger-arrow,
    .settings-native-select-trigger:active > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger:active > .dropdown-trigger-arrow,
    .custom-select.active .custom-select-trigger > svg,
    .config-native-select.open .config-native-select-trigger > .dropdown-trigger-arrow,
    .settings-native-select.open .settings-native-select-trigger > .dropdown-trigger-arrow,
    .items-per-page-custom.open .items-per-page-custom-trigger > .dropdown-trigger-arrow,
    .custom-select-trigger[aria-expanded="true"] > svg,
    .config-native-select-trigger[aria-expanded="true"] > .dropdown-trigger-arrow,
    .settings-native-select-trigger[aria-expanded="true"] > .dropdown-trigger-arrow,
    .items-per-page-custom-trigger[aria-expanded="true"] > .dropdown-trigger-arrow
) :is(path, polyline, line) {
    stroke: var(--control-state-primary) !important;
}
