/* Native server sorting and DataTables share header control/indicator geometry. */
#changecdn .twoip-sort-control,
#changecdn .dt-bootstrap5 table.dataTable thead th .dt-column-header {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  max-width: 100%;
}
#changecdn .twoip-sort-control > .twoip-icon,
#changecdn .dt-bootstrap5 table.dataTable thead th .dt-column-order,
#changecdn .dt-bootstrap5 table.dataTable thead th:is(.dt-orderable-asc,.dt-orderable-desc,.dt-ordering-asc,.dt-ordering-desc) .dt-column-order {
  position: static;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  margin: 0;
  color: var(--twoip-primary);
  opacity: .55;
  font-size: 16px;
  line-height: 1;
}
#changecdn .twoip-sort-control > .twoip-icon.active,
#changecdn .dt-bootstrap5 table.dataTable thead th:is(.dt-ordering-asc,.dt-ordering-desc) .dt-column-order {
  opacity: 1;
}
#changecdn .twoip-data-panel[aria-busy="true"] .table-responsive {
  opacity: .6;
}
#changecdn .twoip-sort-control > .twoip-inline-label { min-width: 0; }
/* Standard tabular captions are atomic; the existing table scroll owner handles
   insufficient space. Property labels, WHOIS prose and layout tables retain
   their separate wrapping contracts. */
#changecdn :is(table.twoip-data-table,table.twoip-table-comparison,table.dataTable) > thead > tr > th {
  white-space: nowrap;
}
#changecdn .twoip-sort-control > .twoip-inline-label,
#changecdn .dt-bootstrap5 table.dataTable thead th .dt-column-title {
  flex: 0 0 auto;
  white-space: nowrap;
}
#changecdn table.twoip-table-comparison > thead > tr > th {
  width: auto;
}
#changecdn table.twoip-table-comparison > t#changecdn > tr > td:first-child {
  white-space: nowrap;
}
#changecdn table.table {
  --bs-table-color: var(--twoip-on-surface); --bs-table-bg: transparent;
  --bs-table-striped-bg: var(--twoip-surface-container-high); --bs-table-hover-bg: var(--twoip-surface-container-high);
  --bs-table-striped-color: var(--twoip-on-surface); --bs-table-hover-color: var(--twoip-on-surface);
  --bs-table-active-bg: var(--twoip-primary-container); --bs-table-active-color: var(--twoip-on-primary-container);
  --bs-table-border-color: var(--twoip-outline-variant);
  font-size: 15px;
}
/* Native table-cell height is a minimum; multiline/expanded content can grow.
   Presentation/layout and permission matrices retain their existing metrics. */
#changecdn table.table:not([role="presentation"]):not(.twoip-table-permission-matrix) > :is(thead,tbody,tfoot) > tr > :is(th,td) {
  box-sizing: border-box; height: var(--twoip-table-row-height);
  padding: var(--twoip-table-cell-padding-block) var(--twoip-table-cell-padding-inline);
  line-height: var(--twoip-table-line-height);
  border-color: var(--twoip-outline-variant); vertical-align: middle;
}
#changecdn table.table:is([role="presentation"],.twoip-table-permission-matrix) :is(th,td) {
  padding: 8px 10px; border-color: var(--twoip-outline-variant); vertical-align: middle;
}
/* First-party data cells share one left axis, including vendor numeric and
   Bootstrap alignment utilities (!important). Layout/permission matrices opt out. */
#changecdn table:not([role="presentation"]):not(.twoip-table-permission-matrix) :is(th,td) {
  text-align: left !important;
  padding-inline: 10px;
}
/* Ordinary words wrap at natural boundaries; responsive strategy owns fit. */
#changecdn table.table :is(th,td) {
  word-break: normal;
  overflow-wrap: normal;
}
#changecdn .dt-bootstrap5 table.dataTable {
  table-layout: auto;
}
#changecdn .dt-bootstrap5 table.dataTable .dt-column-title {
  min-width: 0;
  word-break: normal;
  overflow-wrap: normal;
}
/* A primary entity column retains enough space for ordinary names. */
#changecdn .dt-bootstrap5 table.dataTable .twoip-table-entity {
  min-width: 10rem;
}
#changecdn .twoip-table-comparison .twoip-table-number,
#changecdn .dt-bootstrap5 table.dataTable td.dt-type-numeric {
  white-space: nowrap;
}
/* Keep the available table width stable when responsive rows change height. */
#changecdn .modal-body:has(.dt-container) {
  scrollbar-gutter: stable;
}
/* Utilities reflow by their container, including narrow desktop modals. */
#changecdn .dt-bootstrap5 > .dt-layout-row:not(.dt-layout-table) {
  gap: 8px 0;
}
#changecdn .dt-bootstrap5 > .dt-layout-row:not(.dt-layout-table) > .dt-layout-cell {
  flex: 1 1 auto;
  min-width: min(100%, 18rem);
  max-width: 100%;
}
#changecdn .dt-bootstrap5 .dt-length {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
#changecdn .dt-bootstrap5 .dt-length label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
#changecdn .dt-bootstrap5 .dt-search {
  min-width: 0;
}
#changecdn .dt-bootstrap5 .dt-search input {
  max-width: 100%;
}
#changecdn .t3-mainbody .t3-content table.table > thead > tr > th,
#changecdn table.table > thead > tr > th {
  color: var(--twoip-on-surface-variant); background: var(--twoip-surface-container);
  border-bottom: 1px solid var(--twoip-outline-variant); font-size: 15px; font-family: '2ip-bold'; font-weight: normal;
}
#changecdn table.table > t#changecdn > tr:hover > * { --bs-table-bg-state: var(--twoip-surface-container-high); }
#changecdn table.table > t#changecdn > tr:is(.selected,.table-active) > * { --bs-table-bg-state: var(--twoip-primary-container); background: var(--twoip-primary-container); color: var(--twoip-on-primary-container); }
#changecdn :is(.dt-info,.twoip-table-info) { color: var(--twoip-on-surface-variant); font-size: 14px; }
/* Joomla, custom/AJAX and DataTables pagers share one control family. */
#changecdn .pagination {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end;
  gap: var(--twoip-pagination-gap); float: none; margin: 0; padding: 0; list-style: none;
}
#changecdn .pagination::before,
#changecdn .pagination::after { display: none; }
#changecdn .pagination > li { flex: 0 0 auto; display: block; }
#changecdn .pagination > li > :is(a,span,button,.page-link) {
  display: flex; align-items: center; justify-content: center; float: none;
  width: var(--twoip-pagination-size); min-width: var(--twoip-pagination-size);
  height: var(--twoip-pagination-size); min-height: var(--twoip-pagination-size);
  padding: 0; margin: 0; top: 0; border: 0; border-radius: var(--twoip-pagination-radius);
  line-height: 1; font-size: 15px; color: var(--twoip-pagination-foreground);
  background: transparent; box-shadow: none; text-decoration: none;
  transition: color .15s ease, background-color .15s ease;
}
/* Center the shared icon slot, independent of glyph width or account typography. */
#changecdn .pagination .twoip-icon {
  display: flex; align-items: center; justify-content: center;
  width: 1em; height: 1em; flex: 0 0 auto;
  padding: 0; margin: 0; position: static; line-height: 1;
}
#changecdn .pagination > li.active > :is(a,span,button,.page-link),
#changecdn .pagination [aria-current="page"] {
  color: var(--twoip-pagination-active-foreground); background: var(--twoip-pagination-active);
}
#changecdn .pagination > li:not(.disabled) > :is(a,button,.page-link):hover { background: var(--twoip-pagination-hover); color: var(--twoip-pagination-active-foreground); }
#changecdn .pagination > li:not(.disabled) > :is(a,button,.page-link):active { background: var(--twoip-pagination-active); }
#changecdn .pagination > li.disabled > :is(a,span,button,.page-link) { color: var(--twoip-pagination-disabled); opacity: .5; pointer-events: none; background: transparent; }
#changecdn .t3-content .twoip-table-footer { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 12px; }
#changecdn .t3-content .twoip-table-footer > :first-child { flex: 1 1 auto; width: auto; }
#changecdn .t3-content .twoip-table-footer > :last-child { flex: 0 0 auto; width: auto; max-width: 100%; }
#changecdn .t3-content .twoip-table-footer.row { margin-inline: 0; }
#changecdn .t3-content .twoip-table-footer.row > * { padding-inline: 0; }
#changecdn .t3-content .twoip-table-paging { float: none !important; margin-inline-start: auto; }
@media (max-width: 767px) {
  #changecdn .t3-content .twoip-table-footer > :last-child { flex: 1 1 100%; }
  #changecdn .pagination:not(.dt-paging .pagination) > li:not(.active):not(:nth-child(-n+2)):not(:nth-last-child(-n+2)) { display: none; }
}
#changecdn .dt-container :is(.dt-info,.dt-length,.dt-search) { color: var(--twoip-on-surface-variant); font-size: 14px; }
/* Dialogs and feedback share surfaces, states and color roles. */
#changecdn .modal-content {
  color: var(--twoip-on-surface); background: var(--twoip-surface);
  border: 0; border-radius: var(--twoip-radius-large); box-shadow: var(--twoip-elevation-2);
}
#changecdn .modal-header { padding: 16px 20px; border-bottom: 1px solid var(--twoip-outline-variant); }
#changecdn .modal-title { font-size: 22px; line-height: 1.3; }
#changecdn .modal-body { padding: 16px 20px; }
#changecdn .modal-footer { display: flex; align-items: center; padding: 12px 20px 16px; border-color: var(--twoip-outline-variant); gap: 12px; flex-wrap: wrap; justify-content: flex-end; }
#changecdn .modal-footer form { margin: 0; }
#changecdn .modal-footer .btn { margin: 0; }
/* Keep scrolling inside dialog content; avoid a second shell scrollbar. */
#changecdn:has(> .modal-dialog-centered.modal-dialog-scrollable) { overflow-y: hidden; }
/* Ordinary Bootstrap dialogs use viewport centering and bounded #changecdn scrolling. */
#changecdn .modal-dialog-centered.modal-dialog-scrollable {
  min-height: calc(100% - var(--bs-modal-margin) * 2);
  height: calc(100% - var(--bs-modal-margin) * 2);
  margin-inline: auto;
}
#changecdn .modal-dialog-centered.modal-dialog-scrollable .modal-content { width: 100%; height: auto; max-height: 100%; }
#changecdn .modal-dialog-centered.modal-dialog-scrollable .modal-body { overflow-y: auto; }
@media (max-width: 575px) {
  #changecdn .modal-dialog-centered.modal-dialog-scrollable { width: calc(100% - var(--bs-modal-margin) * 2); }
}

/* Compact labelled filters reuse selector geometry without becoming action buttons. */
#changecdn .twoip-select-control {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: 9px;
  padding-inline-start: var(--twoip-control-padding-inline);
  padding-inline-end: var(--twoip-select-trailing-inset);
  gap: var(--twoip-select-icon-gap);
  font-size: var(--twoip-type-body);
  color: var(--twoip-on-surface);
  background: var(--twoip-surface);
  border: 1px solid var(--twoip-outline);
  border-radius: var(--twoip-radius-small);
  cursor: pointer;
  max-width: 100%;
  min-width: 0;
  text-align: start;
}
#changecdn .twoip-select-control > :not(.twoip-disclosure-arrow) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#changecdn .twoip-select-control .twoip-icon {color:var(--twoip-field-state,var(--st-icon-color));font-size:16px;position:static;margin:0;flex:none}
#changecdn .twoip-select-control:is(:hover,:active) {background:var(--twoip-primary-container);color:var(--twoip-on-primary-container)}
#changecdn .twoip-select-control:focus-visible {outline:2px solid var(--twoip-primary);outline-offset:3px}
/* One overflow owner for native/AJAX tables and the DataTables table row.
   Intrinsic cell widths preserve readable text without widening the page. */
#changecdn :is(.table-responsive,.twoip-service-table-scroll,.twoip-table-scroll) {
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-inline: contain;
}
#changecdn .twoip-table-controls-container {
  overflow: visible;
}
#changecdn :is(.dt-container,.dt-layout-table,.tab-content,.tab-pane,.modal-body) {
  min-inline-size: 0;
  max-inline-size: 100%;
}
#changecdn :is(.table-responsive,.twoip-service-table-scroll,.twoip-table-scroll) > table {
  table-layout: auto;
  width: 100%;
}
#changecdn :is(.table-responsive,.twoip-service-table-scroll,.twoip-table-scroll):focus-visible {
  outline: 2px solid var(--twoip-primary);
  outline-offset: -2px;
}


/* Source shared selector suppresses Bootstrap’s duplicate disclosure triangle. */
#changecdn .twoip-selector-toggle::after {display:none}
#changecdn .dt-container .dt-layout-row:has(.dt-paging) { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 12px; margin-inline: 0; }
#changecdn .dt-container .dt-layout-row:has(.dt-paging) > .dt-layout-cell { padding-inline: 0; }
#changecdn .dt-container .dt-layout-row:has(.dt-paging) > .dt-layout-start { width: auto; flex: 1 1 auto; }
#changecdn .dt-container .dt-layout-row:has(.dt-paging) > .dt-layout-end { width: auto; flex: 0 0 auto; max-width: 100%; }
@media (max-width: 767px) {
  #changecdn .dt-container .dt-layout-row:has(.dt-paging) { margin-inline: 0; }
  #changecdn .dt-container .dt-layout-row:has(.dt-paging) > :is(.dt-layout-start,.dt-layout-end) { flex: 1 1 100%; width: 100%; padding-inline: 0; }
  #changecdn .dt-paging { width: 100%; }
}

/* Ported 2ip CDN component + matching shared presentation. See frontend/cdn-picker-sources.json. */
/* The speedtest server table must not set the modal's intrinsic viewport width. */
#changecdn .modal-dialog {
  --bs-modal-width: 900px;
  color: var(--twoip-color-text);
  font-family: '2ip';
}
#changecdn .modal-body {
  padding: 20px 24px 12px;
}
#changecdn .cdn-country-toggle:hover {
  outline-offset: 3px;
}
#changecdn .cdn-country-toggle:focus-visible {
  outline: 2px solid var(--twoip-primary);
  outline-offset: 3px;
}
#changecdn .table-responsive {
  margin: 4px 0 0;
  border: 0;
}
/* DataTables owns column sizing and container-driven visibility. */
#changecdn #cdn-server-table {
  width: 100%;
}
#changecdn #cdn-server-table td:first-child {
  white-space: nowrap;
}
#changecdn #cdn-server-table td:first-child span {
  display: inline-block;
  vertical-align: middle;
}
#changecdn #cdn-server-table td:nth-child(4),
#changecdn #cdn-server-table td:nth-child(5) {
  white-space: nowrap;
  text-align: right;
}
#changecdn #cdn-server-table t#changecdn tr {
  cursor: pointer;
}
#changecdn #cdn-server-table .cdn-flag,
#changecdn #cdnfilter .cdn-flag {
  width: auto;
  max-width: 28px;
  height: 15px;
  vertical-align: middle;
}
#changecdn .dt-container .dt-layout-row:not(.dt-layout-table) {
  margin: 8px 0;
}
#changecdn .dt-container > .dt-layout-row:first-child {
  margin: 4px 0 4px;
  align-items: center;
}
#changecdn .dt-container .dt-search {
  display: flex;
  align-items: center;
  gap: 8px;
}
#changecdn .dt-container .dt-search {
  justify-content: flex-end;
  width: 100%;
}
#changecdn .dt-container .dt-search .cdn-provider-search {
  --twoip-field-margin-bottom: 0px;
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
}
#changecdn .dt-container .dt-search .cdn-provider-search::before {
  content: none;
}

#changecdn .dt-container .dt-search .twoip-form-group input.form-control {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  margin: 0;
}
#changecdn .dt-container .dt-search .cdn-provider-search .material-input {
  display: none;
}
#changecdn .dt-container .dt-info {
  padding-top: 7px;
  color: var(--twoip-on-surface-variant);
}
#changecdn .modal-footer {
  padding: 8px 20px 12px;
}
@media screen and (max-width: 767px) {
  #changecdn .modal-body {
    padding: 14px 12px 8px;
  }
}
/* CDN picker uses the native DataTables full-width top layout cell. */
#changecdn .dt-container { container: twoip-cdn-picker / inline-size; }
#changecdn .cdn-selection-toolbar {
  display: grid; grid-template-columns: max-content minmax(0,1fr);
  align-items: center; gap: var(--twoip-service-form-control-gap);
}
#changecdn .cdn-country-filter { margin: 0; min-inline-size: 0; }
#changecdn .cdn-country-filter .twoip-selector { display: flex; align-items: center; gap: var(--twoip-service-form-control-gap); }
#changecdn .cdn-country-toggle { block-size: var(--twoip-control-height); min-block-size: var(--twoip-control-height); }
@container twoip-cdn-picker (max-width: 575.98px) {
  #changecdn .cdn-selection-toolbar { grid-template-columns: minmax(0,1fr); }
  #changecdn .cdn-country-toggle { flex: 1; }
}

.twoip-inline-link {
  --twoip-inline-border-style: solid;
  --twoip-inline-border: var(--twoip-link-border);
  --twoip-inline-pressed: var(--twoip-link-pressed);
  color: var(--twoip-link-text); text-decoration: none;
  border: 0; border-bottom: 1px var(--twoip-inline-border-style) var(--twoip-inline-border);
  padding-bottom: 1px; cursor: pointer; box-decoration-break: clone; font: inherit;
  transition: color .15s ease, border-color .15s ease;
}
.twoip-inline-link--action {
  --twoip-inline-border-style: dotted;
  --twoip-inline-border: var(--twoip-link-action-border);
  --twoip-inline-pressed: var(--twoip-link-action-pressed);
}
.twoip-inline-link:is(:hover,:focus-visible,:active,:visited) { text-decoration: none; }
.twoip-inline-link:visited { color: var(--twoip-link-text); }
.twoip-inline-link:is(:hover,:focus-visible) { color: var(--twoip-inline-hover); border-bottom-color: var(--twoip-inline-hover); }
.twoip-inline-link:active { color: var(--twoip-inline-pressed); border-bottom-color: var(--twoip-inline-pressed); }
.twoip-inline-link:focus-visible { outline: 2px solid var(--twoip-link-focus); outline-offset: 3px; }
.twoip-inline-link.twoip-inline-link--with-label { border-bottom: 0; }
.twoip-inline-link--with-label .twoip-inline-label:has(.twoip-inline-label) { border-bottom: 0; }
.twoip-inline-link--with-label .twoip-inline-label:not(:has(.twoip-inline-label)) { text-decoration: none; color: inherit; border-bottom: 1px var(--twoip-inline-border-style) var(--twoip-inline-border); padding-bottom: 1px; box-decoration-break: clone; }
.twoip-inline-link--with-label:is(:hover,:focus-visible) .twoip-inline-label:not(:has(.twoip-inline-label)) { border-bottom-color: var(--twoip-inline-hover); }
.twoip-inline-link--with-label:active .twoip-inline-label:not(:has(.twoip-inline-label)) { border-bottom-color: var(--twoip-inline-pressed); }
.twoip-inline-link > .twoip-panel-title { color: inherit; }
.twoip-inline-link :is(.twoip-icon,.twoip-disclosure-arrow) { display: inline-block; border: 0; color: currentColor; text-decoration: none; }
/* Ordinary link glyphs share every foreground state with their text. Disclosure/state/action icons are separate. */

/* Source presentation.css modal-footer baseline; component padding remains authoritative. */
#changecdn .modal-content .modal-footer {border-top:none}
#changecdn .twoip-selector-list {
    margin-top: 6px !important;
    padding: 4px;
    max-width: calc(100vw - 24px);
    max-height: min(60vh, 360px);
    min-width: 240px;
    background: var(--twoip-surface);
    border-color: var(--twoip-outline-variant);
    border-radius: var(--twoip-radius-medium);
    box-shadow: var(--twoip-elevation-2);
}
#changecdn .twoip-selector .dropdown-menu:not(.show) { display: none; }
#changecdn .twoip-selector-list:not(.twoip-city-popup--searchable) {
    overflow-y: auto;
}
#changecdn .twoip-selector-list .dropdown-item { color: var(--twoip-on-surface); min-height: 48px; padding: 10px 12px; gap: 10px; border-radius: var(--twoip-radius-small); display: flex; align-items: center; white-space: normal; word-break: normal; text-decoration: none; }
#changecdn .twoip-selector-list .twoip-icon { color: currentColor; font-size: 18px; margin: 0; position: static; }
