/* Hostport UI component library.
   Shared Hp* component structure (page header, card, stat card, empty state,
   section) lives in the Ui Razor Class Library (_content/Ui/hp-ui.css) —
   only Hostport-specific components and this portal's token VALUES stay here. */

.hp-deployment-section {
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    background: var(--hp-surface-raised);
}

.hp-data-table-wrap {
    overflow-x: auto;
}

.hp-data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.hp-data-table th {
    padding: 0.75rem 1rem;
    text-align: left;
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
    border-bottom: 1px solid var(--hp-border-subtle);
    white-space: nowrap;
}

.hp-data-table td {
    padding: 0.85rem 1rem;
    color: var(--hp-text);
    border-bottom: 1px solid var(--hp-border-subtle);
    vertical-align: middle;
}

.hp-data-table tbody tr:last-child td {
    border-bottom: none;
}

.hp-data-table tbody tr:hover {
    background: var(--hp-surface-overlay);
}

.hp-data-table .hp-data-table-actions {
    text-align: right;
    white-space: nowrap;
}

.hp-data-table .hp-data-table-mono {
    font-family: var(--hp-font-mono);
    font-size: 0.85rem;
}

.hp-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--hp-radius-pill);
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.4;
    border: 1px solid transparent;
}

.hp-member-you-badge {
    margin-left: 0.5rem;
}

.hp-badge-primary {
    color: var(--hp-primary-accent);
    background: var(--hp-primary-muted);
    border-color: rgba(110, 146, 192, 0.35);
}

/* The text is the lightened state shade, not the pinned state colour: at 12 px the pinned success
   measured 4.37:1 on its 10% tint over --hp-surface-raised and the pinned warning 4.36:1 on its 16%
   tint; the tints stay so the badge keeps its state wash. */
.hp-badge-success {
    color: var(--hp-success-light);
    background: color-mix(in srgb, var(--hp-success) 10%, transparent);
    border-color: color-mix(in srgb, var(--hp-success) 30%, transparent);
}

.hp-badge-warning {
    color: var(--hp-warning-light);
    background: color-mix(in srgb, var(--hp-warning) 16%, transparent);
    border-color: color-mix(in srgb, var(--hp-warning) 30%, transparent);
}

.hp-badge-info {
    color: var(--hp-primary-accent);
    background: var(--hp-primary-muted);
    border-color: rgba(110, 146, 192, 0.35);
}

.hp-badge-danger {
    color: var(--hp-danger-light);
    background: color-mix(in srgb, var(--hp-danger) 16%, transparent);
    border-color: color-mix(in srgb, var(--hp-danger) 30%, transparent);
}

.hp-badge-neutral {
    color: var(--hp-text-secondary);
    background: rgba(148, 163, 184, 0.12);
    border-color: var(--hp-border-subtle);
}

.hp-section-header-bar {
    padding: 0.75rem 1rem;
    background: var(--hp-surface-raised);
    border-bottom: 1px solid var(--hp-border-subtle);
}

.hp-code-snippet {
    margin: 0;
    padding: 0.875rem 1rem;
    background: var(--hp-bg-base);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    overflow-x: auto;
    font-size: var(--hp-font-xs);
    line-height: 1.45;
    color: var(--hp-text-secondary);
}

.hp-icon-primary {
    color: var(--hp-primary-accent);
}

.hp-icon-muted {
    color: var(--hp-text-muted);
}

.hp-icon-ok {
    color: var(--hp-success);
}

/* Job queue "who processes it" chooser: two equal cards, each a complete path. */
.hp-choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
    gap: 1rem;
    align-items: stretch;
}

.hp-choice-card {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    height: 100%;
}

.hp-choice-card-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.hp-choice-card-icon {
    font-size: var(--hp-font-4xl);
}

.hp-choice-card-title {
    margin: 0;
    font-size: var(--hp-font-md);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-choice-card-lead {
    margin: 0.15rem 0 0;
    font-size: var(--hp-font-sm);
    color: var(--hp-text-muted);
}

.hp-choice-card-body {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-top: auto;
}

/* Tunnels — who can reach a new tunnel. In-page options, never a native <select>; an option the
   platform cannot honour yet is drawn disabled with its reason rather than left out, so the
   choice it will become is visible without being a trap. */
.hp-tunnel-access {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--hp-space-3);
}

.hp-tunnel-access-option {
    display: flex;
    flex-direction: column;
    gap: var(--hp-space-1);
    padding: var(--hp-space-3) var(--hp-space-4);
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-radius-lg);
    background: var(--hp-surface);
    color: var(--hp-text);
    font: inherit;
    text-align: left;
}

.hp-tunnel-access-option[aria-checked="true"] {
    border-color: var(--hp-primary);
    background: var(--hp-primary-muted);
}

.hp-tunnel-access-option:disabled {
    background: transparent;
    color: var(--hp-text-muted);
    cursor: not-allowed;
}

.hp-tunnel-access-option:focus-visible {
    outline: 2px solid var(--hp-primary);
    outline-offset: 2px;
}

.hp-tunnel-access-title {
    font-size: var(--hp-font-sm);
    font-weight: 600;
}

.hp-tunnel-access-lead {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-snippet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.hp-processing-status {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.hp-processing-status-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
    flex: 1 1 12rem;
}

.hp-processing-status-action {
    margin-left: auto;
}

.hp-icon-success {
    color: var(--hp-success);
}

.hp-icon-xs {
    font-size: 0.75rem !important;
}

.hp-icon-sm {
    font-size: 0.9rem;
}

.hp-icon-md {
    font-size: var(--hp-font-2xl);
}

.hp-icon-lg {
    font-size: var(--hp-font-4xl);
}

.hp-icon-xl {
    font-size: var(--hp-font-6xl);
}

.hp-icon-xxl {
    font-size: 3rem;
}

.hp-icon-display {
    font-size: 4rem;
}

.hp-danger-zone {
    border: 1px solid color-mix(in srgb, var(--hp-danger) 35%, transparent);
    background: color-mix(in srgb, var(--hp-danger) 8%, transparent);
}

/* danger-light: this utility lands on body text; the pinned danger is a UI color (see theme). */
.hp-text-danger {
    color: var(--hp-danger-light);
}

.hp-text-warning {
    color: var(--hp-warning);
}

.hp-text-success {
    color: var(--hp-success);
}

.hp-list-indented {
    margin-left: 1.25rem;
    margin-bottom: 0;
}

.hp-muted-surface {
    background: var(--hp-surface-raised);
}

.hp-filter-badge {
    cursor: pointer;
}

.hp-filter-badge.hp-filter-badge-active {
    box-shadow: 0 0 0 2px rgba(110, 146, 192, 0.35);
}

.hp-deploy-card {
    transition: all 0.3s ease;
}

.hp-deploy-card-status-failed {
    border-left: 2px solid var(--hp-danger);
}

.hp-deploy-card-status-success {
    border-left: 2px solid var(--hp-success);
}

.hp-deploy-card-status-warning {
    border-left: 2px solid var(--hp-warning);
}

.hp-deploy-card-status-info {
    border-left: 2px solid var(--hp-primary-accent);
}

.hp-deploy-icon {
    font-size: var(--hp-font-2xl);
}

.hp-deploy-icon-failed {
    color: var(--hp-danger);
}

.hp-deploy-icon-success {
    color: var(--hp-success);
}

.hp-deploy-icon-warning {
    color: var(--hp-warning);
    animation: hp-pulse 2s infinite;
}

.hp-deploy-icon-info {
    color: var(--hp-primary-accent);
}

.hp-stack-compose {
    display: flex;
    flex-direction: column;
    gap: 2rem;
    padding-top: 0.75rem;
}

.hp-stack-dialog-body {
    padding: 0 0.15rem;
}

.hp-stack-inline-error {
    margin-top: 0.5rem;
}

.hp-stack-section {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.hp-stack-section-head {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.hp-stack-section-title {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--hp-text);
}

.hp-stack-section-lead {
    margin: 0;
    font-size: var(--hp-font-sm);
    line-height: 1.45;
    color: var(--hp-text-muted);
}

.hp-stack-setup-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}

@media (max-width: 700px) {
    .hp-stack-setup-grid {
        grid-template-columns: 1fr;
    }
}

.hp-stack-combobox {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    max-width: 36rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    background: var(--hp-surface);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.hp-stack-combobox:focus-within {
    border-color: var(--hp-primary);
    box-shadow: var(--hp-focus-ring);
}

.hp-stack-combobox-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 2.75rem;
    color: var(--hp-text-muted);
    pointer-events: none;
}

.hp-stack-combobox-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.85rem 0.5rem 0.85rem 0;
    border: none;
    background: transparent;
    color: var(--hp-text);
    font-size: 0.9375rem;
    line-height: 1.4;
    outline: none;
}

.hp-stack-combobox-input::placeholder {
    color: var(--hp-text-muted);
}

.hp-stack-combobox-input::-webkit-search-cancel-button {
    display: none;
}

.hp-stack-combobox-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 2.25rem;
    margin-inline-end: 0.35rem;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--hp-text-muted);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.hp-stack-combobox-clear:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--hp-text);
}

.hp-stack-combobox-panel {
    position: absolute;
    z-index: 30;
    inset-inline: 0;
    inset-block-start: calc(100% + 0.5rem);
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    max-height: 18rem;
    overflow-y: auto;
    padding: 0.4rem;
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-radius);
    background: var(--hp-surface-raised);
    box-shadow: var(--hp-shadow);
}

.hp-stack-combobox-option {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.65rem 0.75rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text);
    text-align: start;
    cursor: pointer;
    transition: background 0.12s ease;
}

.hp-stack-combobox-option:hover {
    background: var(--hp-primary-muted);
}

.hp-stack-combobox-option-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    flex: 1 1 auto;
    min-width: 0;
}

.hp-stack-combobox-option-title {
    font-size: 0.9375rem;
    font-weight: 600;
}

.hp-stack-combobox-option-meta {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-stack-combobox-option-add {
    flex: 0 0 auto;
    font-size: 1.125rem !important;
    color: var(--hp-primary-accent);
    opacity: 0.7;
    transition: opacity 0.12s ease;
}

.hp-stack-combobox-option:hover .hp-stack-combobox-option-add {
    opacity: 1;
}

.hp-stack-combobox-empty {
    padding: 1rem 0.75rem;
    font-size: var(--hp-font-sm);
    color: var(--hp-text-muted);
    text-align: center;
}

.hp-stack-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.65rem;
    padding: 2.5rem 1.5rem;
    border: 1px dashed var(--hp-border);
    border-radius: var(--hp-radius);
    background: rgba(255, 255, 255, 0.015);
    text-align: center;
}

.hp-stack-empty-icon-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--hp-radius-round);
    background: var(--hp-primary-muted);
    color: var(--hp-primary-accent);
    font-size: var(--hp-font-2xl);
}

.hp-stack-empty-title {
    margin: 0;
    font-size: var(--hp-font-md);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-stack-empty-text {
    margin: 0;
    max-width: 26rem;
    font-size: var(--hp-font-sm);
    line-height: 1.5;
    color: var(--hp-text-muted);
}

.hp-stack-quickpicks {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
    max-width: 34rem;
}

.hp-stack-quickpick {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.75rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-pill);
    background: var(--hp-surface);
    color: var(--hp-text);
    font-size: var(--hp-font-xs);
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.hp-stack-quickpick:hover {
    border-color: var(--hp-primary);
    background: var(--hp-primary-muted);
}

.hp-stack-quickpick-add {
    font-size: 1rem !important;
    color: var(--hp-primary-accent);
}

.hp-stack-service-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.hp-stack-service-card {
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    background: rgba(255, 255, 255, 0.02);
    overflow: hidden;
    box-shadow: var(--hp-shadow-sm);
}

.hp-stack-service-card--web {
    border-inline-start: 2px solid var(--hp-primary);
}

.hp-stack-service-card--db {
    border-inline-start: 2px solid var(--hp-success);
}

.hp-stack-service-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0 1rem 0 0;
    transition: background 0.12s ease;
}

.hp-stack-service-head:hover {
    background: rgba(255, 255, 255, 0.03);
}

/* The disclosure itself: a real button that inherits the row's layout, so keyboard users get
   native Enter/Space instead of a mouse-only div. */
.hp-stack-service-toggle {
    display: flex;
    flex: 1;
    min-width: 0;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 0 0.85rem 1rem;
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    user-select: none;
}

.hp-stack-service-titles {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    flex: 1 1 auto;
    min-width: 0;
}

.hp-stack-service-name {
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--hp-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-stack-service-summary {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-stack-status {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    padding: 0.25rem 0.6rem;
    border-radius: var(--hp-radius-pill);
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    white-space: nowrap;
}

.hp-stack-status .rzi {
    font-size: 0.9375rem;
}

.hp-stack-status--ok {
    background: color-mix(in srgb, var(--hp-success) 14%, transparent);
    color: var(--hp-success);
}

.hp-stack-status--warn {
    background: color-mix(in srgb, var(--hp-warning) 16%, transparent);
    color: var(--hp-warning);
}

.hp-stack-status--busy {
    background: rgba(255, 255, 255, 0.06);
    color: var(--hp-text-muted);
}

/* Per-service price, in the card header beside the status chip. */
.hp-stack-service-cost {
    flex: 0 0 auto;
    font-size: var(--hp-font-xs);
    font-weight: 600;
    color: var(--hp-text-muted);
    white-space: nowrap;
}

/* Running total for the whole stack, on the build step. */
.hp-stack-live-total {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.75rem 1rem;
    border: 1px solid var(--hp-border);
    border-radius: 0.5rem;
    background: rgba(255, 255, 255, 0.02);
}

.hp-stack-live-total-label {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-stack-live-total-muted {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-stack-chevron {
    flex: 0 0 auto;
    color: var(--hp-text-muted);
    transition: transform 0.15s ease;
}

.hp-stack-chevron.is-open {
    transform: rotate(180deg);
}

.hp-stack-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 2rem;
    height: 2rem;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--hp-text-muted);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.hp-stack-icon-btn:hover {
    background: color-mix(in srgb, var(--hp-danger) 12%, transparent);
    color: var(--hp-danger);
}

.hp-stack-service-body {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding: 1.15rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-stack-field-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.85rem 1rem;
}

@media (max-width: 900px) {
    .hp-stack-field-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 560px) {
    .hp-stack-field-grid {
        grid-template-columns: 1fr;
    }
}

.hp-stack-subsection {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding-top: 1rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-stack-subsection-title {
    margin: 0;
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-stack-advanced-prompt {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
}

.hp-stack-field-hint {
    margin: 0.5rem 0 0;
    font-size: var(--hp-font-xs);
    line-height: 1.4;
}

.hp-stack-field-hint--error {
    color: var(--hp-danger-light);
}

.hp-stack-kind-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.22rem 0.55rem;
    border-radius: var(--hp-radius-pill);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
}

.hp-stack-kind-web {
    background: rgba(110, 146, 192, 0.22);
    color: var(--hp-primary-accent);
}

.hp-stack-kind-db {
    background: color-mix(in srgb, var(--hp-success) 10%, transparent);
    color: var(--hp-success);
}

.hp-stack-connections {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.hp-stack-connection-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    background: rgba(255, 255, 255, 0.02);
}

.hp-stack-connection-app {
    flex: 0 0 auto;
    min-width: 8rem;
    font-size: var(--hp-font-sm);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-stack-connection-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    flex: 1 1 auto;
}

.hp-stack-connection-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.65rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-pill);
    background: rgba(0, 0, 0, 0.15);
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.hp-stack-connection-chip.is-active {
    border-color: color-mix(in srgb, var(--hp-success) 45%, transparent);
    background: color-mix(in srgb, var(--hp-success) 10%, transparent);
    color: var(--hp-text);
}

.hp-stack-review-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    background: var(--hp-surface);
    overflow: hidden;
}

.hp-stack-review-row {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 1.1rem;
}

.hp-stack-review-row + .hp-stack-review-row {
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-stack-review-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1 1 auto;
    min-width: 0;
}

.hp-stack-review-name {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--hp-text);
}

.hp-stack-review-meta {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-stack-review-links {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--hp-font-xs);
    color: var(--hp-success);
}

.hp-stack-review-links .rzi {
    font-size: 0.9375rem;
}

.hp-stack-review-cost {
    flex: 0 0 auto;
    font-size: var(--hp-font-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--hp-text);
    white-space: nowrap;
}

.hp-stack-summary-card {
    padding: 1.15rem 1.25rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    background: var(--hp-surface);
    box-shadow: var(--hp-shadow-sm);
}

.hp-stack-summary-ack {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-top: 1rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--hp-border-subtle);
    font-size: var(--hp-font-sm);
    color: var(--hp-text-secondary);
    cursor: pointer;
}

.hp-stack-payload {
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    background: var(--hp-surface);
}

.hp-stack-payload > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.85rem 1.1rem;
    font-size: var(--hp-font-sm);
    color: var(--hp-text-secondary);
    cursor: pointer;
    user-select: none;
}

.hp-stack-payload > summary .rzi {
    font-size: 1.05rem;
    color: var(--hp-text-muted);
}

.hp-stack-payload-body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0 1.1rem 1.1rem;
}

.hp-stack-json-preview {
    width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: 1rem 1.1rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    background: var(--hp-bg-deepest);
    color: var(--hp-text-secondary);
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
    line-height: 1.5;
    overflow: auto;
    max-height: 32rem;
    white-space: pre-wrap;
    word-break: break-word;
}

@keyframes hp-pulse {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.5;
    }
}

@media (max-width: 768px) {
    .hp-page-header-title {
        font-size: var(--hp-font-2xl);
    }

    .hp-page-header-actions {
        width: 100%;
        justify-content: flex-start;
    }
}

/* Header navigation */

.hp-text-muted {
    color: var(--hp-text-muted);
}

/* Header actions (account) */

/* Comp 18's session cluster is quiet text on the deep frame, not bordered chips. */
.hp-header-action-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.4rem 0.5rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.hp-header-action-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--hp-text);
    border-color: var(--hp-border);
}

.hp-header-action-chevron {
    font-size: 1rem !important;
    opacity: 0.7;
}

.hp-header-dropdown {
    min-width: 11rem;
}


.hp-header-tenant {
    display: flex;
    align-items: center;
}



.account-menu {
    position: relative;
    z-index: 1200;
}

.account-menu-card {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    width: min(320px, calc(100vw - 2rem));
    max-height: min(80vh, 640px);
    overflow-y: auto;
    z-index: 1201;
}

.account-menu-section {
    padding-top: 0.75rem;
    margin-top: 0.75rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.account-menu-section-last {
    margin-bottom: 0;
}

.account-menu-section-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
    margin-bottom: 0.5rem;
}

.account-menu-hint {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    line-height: 1.4;
    margin: 0 0 0.5rem;
}

.account-menu-empty {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    margin: 0 0 0.5rem;
}

.account-menu-org-list {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin-bottom: 0.35rem;
}

.account-menu-org-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.45rem 0.55rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--hp-text-secondary);
    font-size: var(--hp-font-xs);
    cursor: pointer;
    text-align: left;
    transition: background 0.15s ease, color 0.15s ease;
}

.account-menu-org-item:hover:not(:disabled):not([aria-checked="true"]) {
    background: rgba(255, 255, 255, 0.06);
    color: var(--hp-text);
}

.account-menu-org-item:disabled,
.account-menu-org-item[aria-checked="true"] {
    cursor: default;
    opacity: 1;
}

.account-menu-org-item-active,
.hp-crumb-menu .hp-dropdown-action[aria-selected="true"] {
    background: color-mix(in srgb, var(--hp-primary) 12%, transparent);
    color: var(--hp-primary-accent);
}

.account-menu-org-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.account-menu-org-check {
    font-size: 1rem !important;
    color: var(--hp-primary-accent);
}

.account-menu-section-actions {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.hp-dropdown-action-compact {
    padding: 0.4rem 0.55rem;
    font-size: var(--hp-font-xs);
}

.hp-org-switcher {
    position: relative;
    z-index: 1200;
}

/* The org switcher as the rail's workspace block. Its menu doubles as the Organization
   area's front door (the section is RailHidden), so these links are the registry's. */
.hp-rail-org {
    position: relative;
    padding: 0 0 0.75rem;
    margin-bottom: 0.5rem;
}

.hp-rail-org-trigger {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.45rem 0;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text);
    font: inherit;
    font-size: var(--hp-font-sm);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.hp-rail-org-trigger:hover {
    background: var(--hp-surface-overlay);
}

.hp-rail-org-trigger .hp-org-chip-name {
    flex: 1;
    min-width: 0;
}

.hp-rail-org-chevron {
    font-size: var(--hp-font-md) !important;
    opacity: 0.6;
}

/* Owns ALL of this panel's geometry. It used to borrow .account-menu-card, whose right:0 and
   width:320px were written for the header account menu — both anchors then applied at once, the
   box was over-constrained, and a 320px panel hung ~88px past the 15rem rail. Anchor to the
   trigger's own width instead; long organization names ellipsis inside it. */
.hp-rail-org-menu {
    position: absolute;
    top: calc(100% + 0.35rem);
    inset-inline-start: 0;
    width: 100%;
    max-height: 70vh;
    overflow-y: auto;
    z-index: 1200;
}

/* A collapsed rail is 3.75rem wide — too narrow to anchor the panel to. */
.hp-rail-collapsed .hp-rail-org-menu {
    width: max-content;
    min-width: 13rem;
}

.hp-rail-org-menu-actions {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.account-menu-org-list + .hp-rail-org-menu-actions {
    padding-top: 0.5rem;
    margin-top: 0.5rem;
    border-top: 1px solid var(--hp-border-subtle);
}

/* The register action grammar (see .hp-registry-action): a quiet mono "+ new …" in periwinkle,
   not a menu row — the row treatment belongs to destinations, and this is a verb. */
.hp-org-menu-new {
    display: block;
    width: 100%;
    margin-top: 0.15rem;
    padding: 0.35rem 0.55rem;
    border: none;
    border-radius: var(--hp-radius);
    background: none;
    text-align: start;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-rail-font-label);
    font-weight: 400;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--hp-primary-accent);
    cursor: pointer;
}

.hp-org-menu-new:hover {
    color: var(--hp-primary-light);
    background: var(--hp-surface-hover);
}

.hp-rail-collapsed .hp-rail-org .hp-org-chip-name,
.hp-rail-collapsed .hp-rail-org .hp-rail-org-chevron {
    display: none;
}

.hp-org-chip-loading {
    width: 6rem;
    height: 1.75rem;
    border-radius: var(--hp-radius-sm);
    background: rgba(255, 255, 255, 0.06);
}

.hp-org-chip-icon {
    font-size: 1rem !important;
    opacity: 0.75;
}

.hp-org-chip-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
    color: var(--hp-text);
}

.hp-billing-relationship-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    border-radius: var(--hp-radius-sm);
    background: color-mix(in srgb, var(--hp-primary) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--hp-primary) 20%, transparent);
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
}

.hp-billing-section-intro {
    margin-bottom: 0.75rem;
}

.account-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1199;
}

.account-menu-user {
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--hp-border-subtle);
    margin-bottom: 0.75rem;
}

.account-menu-name {
    font-weight: 600;
    word-break: break-word;
    color: var(--hp-text);
    font-size: 0.9375rem;
}

.account-menu-email {
    color: var(--hp-text-muted);
    word-break: break-all;
    font-size: var(--hp-font-xs);
    margin-top: 0.15rem;
}

.account-menu-meta {
    color: var(--hp-text-muted);
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-2xs);
    margin-top: 0.35rem;
}

.account-menu-actions {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.hp-dropdown-panel {
    background: var(--hp-surface-raised);
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-radius-sm);
    box-shadow: var(--hp-shadow);
    padding: 0.85rem;
}

.hp-dropdown-action {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.55rem 0.65rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--hp-text-secondary);
    font-size: var(--hp-font-sm);
    font-weight: 500;
    cursor: pointer;
    text-align: left;
    transition: background 0.15s ease, color 0.15s ease;
}

.hp-dropdown-action:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--hp-text);
}

.hp-dropdown-action-danger {
    color: var(--hp-danger-light);
}

.hp-dropdown-action-danger:hover {
    background: color-mix(in srgb, var(--hp-danger) 12%, transparent);
    color: var(--hp-danger-light);
}

/* Wizard flows (RadzenSteps) */

.hp-wizard-shell {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    background: var(--hp-surface-raised);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    padding: 1.25rem;
    box-shadow: var(--hp-shadow-sm);
    box-sizing: border-box;
}

.hp-wizard-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
}

/* ::deep only works in scoped .razor.css — in this global sheet it made every rule below
   invalid, so browsers dropped them all. Plain descendant selectors do the same job here. */
.hp-wizard-shell .rz-steps {
    margin-bottom: 1.25rem;
}

.hp-wizard-shell .rz-steps-buttons {
    display: none;
}

/* Step titles speak the Systemkarta rail grammar (comp 20's deployment rail: lowercase-set
   mono, letterspaced) so a wizard's progress reads in the same voice as a deployment's. */
.hp-wizard-shell .rz-steps-title {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-wizard-shell .rz-steps-item.rz-state-highlight .rz-steps-number {
    background: var(--hp-gradient-primary);
    border-color: var(--hp-primary);
}

.hp-wizard-shell .rz-steps-item.rz-state-highlight .rz-steps-title {
    color: var(--hp-primary-accent);
}

.hp-wizard-footer {
    flex-shrink: 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    margin: 0.75rem -1.25rem -1.25rem;
    padding: 0.875rem 1.25rem;
    border-top: 1px solid var(--hp-border);
    background: var(--hp-surface);
    box-sizing: border-box;
}

.rz-dialog.hp-wizard-dialog .hp-wizard-footer {
    background: var(--hp-surface-raised);
}

.hp-card.hp-wizard-panel {
    background: var(--hp-surface-overlay);
    border: 1px solid var(--hp-border-subtle);
    box-shadow: none;
}

.hp-wizard-footer-actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-left: auto;
}

.hp-wizard-page {
    min-height: min(70vh, 720px);
}

/* Checklist panel above the wizard footer explaining a disabled Next/Create button */

.hp-wizard-blockers {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    flex-shrink: 0;
    margin-top: 0.75rem;
    padding: 0.9rem 1.1rem;
    border: 1px solid color-mix(in srgb, var(--hp-warning) 35%, transparent);
    border-radius: var(--hp-radius);
    background: color-mix(in srgb, var(--hp-warning) 7%, transparent);
}

.hp-wizard-blockers-icon {
    color: var(--hp-warning);
    margin-top: 0.1rem;
}

.hp-wizard-blockers-body {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

.hp-wizard-blockers-title {
    font-size: var(--hp-font-sm);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-wizard-blockers-body ul {
    margin: 0;
    padding-inline-start: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-size: var(--hp-font-xs);
    line-height: 1.45;
    color: var(--hp-text-secondary);
}

.rz-dialog.hp-wizard-dialog {
    /* Mirrors HostportDialogOptions.WizardWidth/Height — change both together. One size for
       every dialog in the product: near-fullscreen work surface, capped so it doesn't sprawl
       on very wide monitors. Below 768px the media query takes over with true fullscreen. */
    width: min(92vw, 1600px) !important;
    height: min(92vh, 1240px) !important;
    max-width: min(92vw, 1600px);
    max-height: min(92vh, 1240px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-color: var(--hp-border);
    box-shadow: var(--hp-shadow);
}

/* Phones and portrait tablets: wizards take the whole screen. A floating sheet at this size
   only adds edges to scroll past, and the fixed height stops the keyboard from collapsing
   the step content. */
@media (max-width: 768px) {
    .rz-dialog.hp-wizard-dialog {
        width: 100dvw !important;
        height: 100dvh !important;
        max-width: 100dvw;
        max-height: 100dvh;
        border-radius: 0;
    }
}

/* Long unbroken values (URLs, connection strings, generated keys) wrap instead of pushing
   any dialog into horizontal scroll. overflow-wrap inherits, so one rule covers all content. */
.rz-dialog .rz-dialog-content {
    overflow-wrap: break-word;
}

.rz-dialog .rz-dialog-title {
    /* min-width 0 lets the flex titlebar actually shrink the title so ellipsis can kick in */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Radzen caps confirm/alert boxes at 400px, which crowds two buttons plus a real sentence. */
.rz-dialog-confirm,
.rz-dialog-alert {
    max-width: min(640px, calc(100vw - 2rem));
}

.rz-dialog.hp-wizard-dialog .rz-dialog-titlebar {
    flex: 0 0 auto;
    border-block-end: 1px solid var(--hp-border-subtle);
}

.rz-dialog.hp-wizard-dialog .rz-dialog-content,
.rz-dialog.hp-wizard-dialog .hp-wizard-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.rz-dialog.hp-wizard-dialog .hp-wizard-shell {
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    border: none;
    border-radius: 0;
    box-shadow: none;
}

/* Dashboard grid */

/* Page stack spacing */

.hp-page-stack {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

/* Reading measure for stacked form pages. Centred, or the cap would just leave the form pinned
   to the left edge of the 1440px shell. Not for pages built on data grids — squeezing a table to
   640px is worse than letting it use the shell width. */
.hp-page-narrow {
    max-width: 640px;
    margin-inline: auto;
}

.hp-page-account {
    max-width: 880px;
}

.hp-account-hub {
    width: 100%;
    max-width: 880px;
    margin: 0 auto;
}

.hp-stat-row {
    display: grid;
    width: 100%;
    /* minmax(0, 1fr) forces every card onto one row at any width — four cards at 375px is
       ~74px each. The min(100%, 9rem) floor lets the row wrap to 2×2 (then 1-up) instead. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
    gap: 1rem;
    align-items: stretch;
}

.hp-stat-row > .hp-stat-card {
    height: 100%;
}

.hp-billing-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    padding: 0.25rem 0 0.5rem;
}

.hp-billing-filter-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.hp-billing-filter-project {
    margin-left: auto;
    flex: 0 1 12rem;
}

@media (max-width: 640px) {
    .hp-billing-filter-project {
        margin-left: 0;
        flex: 1 1 100%;
        width: 100%;
    }
}

.hp-billing-history-filter {
    align-items: flex-end;
}

.hp-billing-history-month,
.hp-billing-history-sort {
    min-width: min(10rem, 100%);
    flex: 0 1 12rem;
}

.hp-billing-table-wrap {
    overflow-x: auto;
}

.hp-billing-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--hp-font-sm);
}

.hp-billing-table th,
.hp-billing-table td {
    padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--hp-border-subtle);
    text-align: left;
    vertical-align: top;
}

.hp-billing-table th {
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    color: var(--hp-text-muted);
    background: var(--hp-surface-muted);
}

.hp-billing-table-num {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.hp-billing-table-meta {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-billing-service-block {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding-top: 0.25rem;
}.hp-portal-browser-card {
    overflow: hidden;
}

.hp-portal-browser-toolbar {
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--hp-border-subtle);
    background: var(--hp-surface-raised);
}

.hp-config-grid {
    display: grid;
    /* auto-fit, not auto-fill: auto-fill kept empty 160px tracks, so a card with two values (an
       organization id, an email) truncated them in a 160px cell beside 700px of nothing. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
    gap: 1rem 1.5rem;
}

/* Long mono values (endpoint URLs) need a wider cell before they read as one line. */
.hp-config-grid-wide {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}

.hp-config-item-label {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    margin: 0 0 0.25rem;
}

.hp-config-item-value {
    font-size: 0.9375rem;
    color: var(--hp-text);
    margin: 0;
    word-break: break-word;
}

.hp-config-item-value.hp-mono {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-sm);
}

.hp-config-item-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

/* Resource detail shell */

.hp-detail-topbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Comp-19 detail frame: swappable stage left, fixed panel right. The panel is the identity
   column and never changes when the view does (owner ruling 2026-08-07) — state and actions
   must stay visible from every view. */

.hp-detail-frame {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 400px;
    gap: 1.5rem;
    align-items: start;
}

.hp-detail-stage {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.hp-detail-stage-head {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    min-height: 2rem;
}

/* The view's one-line explainer (heuristic 10): what the stage is for, in the muted voice, under
   the rail and above any alert — one place, every page. */
.hp-detail-stage-explainer {
    margin: 0.75rem 0 0;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    max-width: 64ch;
}

/* Wraps rather than scrolls: with the scrollbar hidden, the eighth view on a database page
   (SETTINGS) was simply gone at 1440px once the labels reached the type floor. The gap is what
   lets the web app's eight views sit on one line beside the 400px panel at 1440px. */
.hp-view-rail {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.25rem 1.1rem;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    letter-spacing: 0.15em;
    text-transform: uppercase;
}

.hp-view-rail-item {
    background: none;
    border: none;
    padding: 0.4rem 0 0.5rem;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: var(--hp-text-muted);
    cursor: pointer;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
}

.hp-view-rail-item:hover {
    color: var(--hp-text);
}

.hp-view-rail-item--active {
    color: var(--hp-text);
    border-bottom-color: var(--hp-primary);
}

/* 3.5rem is the shell header height (same constant .hp-rail's sticky math uses). */
.hp-detail-panel {
    position: sticky;
    top: calc(3.5rem + 1.5rem);
    display: flex;
    flex-direction: column;
    background: var(--hp-bg-deepest);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    max-height: calc(100vh - 3.5rem - 3rem);
    overflow-y: auto;
}

.hp-detail-panel-head {
    padding: 1.25rem 1.375rem 1rem;
}

.hp-detail-panel-name {
    margin: 0;
    font-size: var(--hp-font-2xl);
    font-weight: 800;
    color: var(--hp-text);
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.hp-detail-panel-type {
    margin-top: 0.4rem;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-detail-panel-badges {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
}

.hp-detail-panel-stats {
    display: grid;
    /* auto-fit, not a fixed 3: pages carry three or four stat boxes and both must wrap evenly. */
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: 0.625rem;
    padding: 0 1.375rem 1.125rem;
}

.hp-detail-panel-stats > .hp-stat-card {
    padding: 0.75rem 0.875rem;
}

.hp-detail-panel-body {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding: 0 1.375rem 1.25rem;
    border-top: 1px solid var(--hp-border-subtle);
    padding-top: 1.125rem;
}

/* Why a disabled action is disabled, printed beside it: a reason that lives only in a title
   attribute is invisible on a phone and to a keyboard user. */
.hp-action-hint {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    max-width: 18rem;
}

.hp-detail-panel-actions {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    flex-wrap: wrap;
    padding: 1rem 1.375rem 1.25rem;
    border-top: 1px solid var(--hp-border-subtle);
    /* The action row must survive a panel that scrolls: it is the reason the panel exists. */
    position: sticky;
    bottom: 0;
    background: var(--hp-bg-deepest);
}

/* Desktop never shows the strip: the panel beside the stage carries the identity. */
.hp-detail-identity {
    display: none;
}

.hp-detail-identity-name {
    font-size: var(--hp-font-2xl);
    font-weight: 800;
    line-height: 1.2;
    overflow-wrap: anywhere;
}

@media (max-width: 1180px) {
    .hp-detail-frame {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Identity strip, then the view rail and the stage, then the panel with its stats, facts and
       actions. The panel used to come first (order: -1) and pushed the rail a full screen down
       on a phone. */
    .hp-detail-identity {
        display: flex;
        flex-direction: column;
        gap: 0.4rem;
    }

    .hp-detail-panel {
        position: static;
        max-height: none;
    }

    .hp-detail-panel-head {
        display: none;
    }

}

/* Compact billing plan card */

.hp-plan-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.hp-plan-card-main {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
    flex: 1 1 16rem;
}

.hp-plan-card-name-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.hp-plan-card-name {
    font-size: var(--hp-font-md);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-plan-card-caps {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-plan-card-side {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-shrink: 0;
}

.hp-plan-card-price {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--hp-text);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-plan-card-price-period {
    font-size: var(--hp-font-2xs);
    font-weight: 400;
    color: var(--hp-text-muted);
    margin-left: 0.15rem;
}

.hp-plan-card-extra {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-account-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1.25rem;
}

.hp-account-nav-card {
    height: 100%;
}

.hp-inline-legal-nav {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--hp-font-xs);
}

.hp-inline-legal-nav ::deep .rz-link {
    color: var(--hp-text-muted);
    text-decoration: none;
}

.hp-inline-legal-nav ::deep .rz-link:hover {
    color: var(--hp-primary-accent);
}

.hp-inline-legal-nav-sep {
    color: var(--hp-text-muted);
    opacity: 0.55;
    user-select: none;
}

/* Deployments + Support share one edge-tab design; only the vertical offset differs.
   The tab used to park itself 80% off-screen (translateX(calc(100% - 38px))) and slide in on
   hover: at rest it read as a clipped rendering artifact rather than a control, and a keyboard
   user could focus something they could not see. Now the whole pill is always on screen and it
   is the LABEL that expands — on hover and on focus alike. */
.hp-workflow-drawer-toggle,
.hp-feedback-drawer-toggle {
    position: fixed;
    right: 0;
    transform: translateY(-50%);
    z-index: 1090;
    display: inline-flex;
    align-items: center;
    gap: 0;
    padding: 0.6rem 0.65rem;
    border: 1px solid var(--hp-border);
    border-right: none;
    border-radius: var(--hp-radius) 0 0 var(--hp-radius);
    background: var(--hp-surface-raised);
    color: var(--hp-text-secondary);
    font-size: var(--hp-font-xs);
    font-weight: 600;
    cursor: pointer;
    box-shadow: var(--hp-shadow-sm);
    transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
    white-space: nowrap;
}

.hp-workflow-drawer-toggle {
    top: calc(50% - 2.75rem);
}

.hp-feedback-drawer-toggle {
    top: calc(50% + 2.75rem);
}

/* Phones: the two tabs floated over page buttons ("View usage and estim…"). They already sit
   in the header's action cluster in the DOM; drop the fixed placement and let them be the
   icon buttons beside the account menu. */
@media (max-width: 640px) {
    .hp-workflow-drawer-toggle,
    .hp-feedback-drawer-toggle {
        position: static;
        transform: none;
        width: 2.5rem;
        height: 2.5rem;
        justify-content: center;
        padding: 0;
        border: 1px solid transparent;
        border-radius: var(--hp-radius-sm);
        background: transparent;
        box-shadow: none;
    }

    .hp-workflow-drawer-toggle .hp-edge-tab-label,
    .hp-feedback-drawer-toggle .hp-edge-tab-label {
        display: none;
    }
}

.hp-workflow-drawer-toggle:hover,
.hp-feedback-drawer-toggle:hover,
.hp-workflow-drawer-toggle:focus-visible,
.hp-feedback-drawer-toggle:focus-visible {
    background: var(--hp-surface-overlay);
    color: var(--hp-text);
    border-color: var(--hp-primary);
    box-shadow: var(--hp-shadow);
}

.hp-edge-tab-label {
    max-width: 0;
    overflow: hidden;
    opacity: 0;
    white-space: nowrap;
    transition: max-width 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s ease, margin-left 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}

.hp-workflow-drawer-toggle:hover .hp-edge-tab-label,
.hp-feedback-drawer-toggle:hover .hp-edge-tab-label,
.hp-workflow-drawer-toggle:focus-visible .hp-edge-tab-label,
.hp-feedback-drawer-toggle:focus-visible .hp-edge-tab-label {
    max-width: 10rem;
    margin-left: 0.5rem;
    opacity: 1;
}

.hp-workflow-drawer-toggle.active,
.hp-feedback-drawer-toggle.active {
    color: var(--hp-primary-accent);
    background: rgba(110, 146, 192, 0.22);
    border-color: rgba(110, 146, 192, 0.45);
    box-shadow: inset 0 0 0 1px rgba(110, 146, 192, 0.45);
}

/* On phones the vertically-centered tabs sit exactly over centered page copy (the first-run
   CTA at 390px); park them low instead, clear of the crash banner's bottom strip. */
@media (max-width: 640px) {
    .hp-workflow-drawer-toggle {
        top: auto;
        bottom: 5rem;
        transform: none;
    }

    .hp-feedback-drawer-toggle {
        top: auto;
        bottom: 1.5rem;
        transform: none;
    }
}

.hp-workflow-drawer-toggle .rzi,
.hp-feedback-drawer-toggle .rzi {
    font-size: 1.15rem;
    opacity: 0.9;
}

.hp-drawer-portal {
    display: contents;
}

.hp-drawer-dialog {
    outline: none;
}

.hp-workflow-drawer-backdrop,
.hp-feedback-drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1300;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(2px);
    transition: opacity 0.2s ease;
}

.hp-workflow-drawer,
.hp-feedback-drawer {
    position: fixed;
    top: 0;
    right: 0;
    width: min(560px, 100vw);
    max-width: 100%;
    height: 100vh;
    z-index: 1310;
    background: var(--hp-surface-overlay);
    border-left: 1px solid var(--hp-border);
    padding: 1.75rem 1.5rem;
    overflow-y: auto;
    box-shadow: var(--hp-shadow);
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    box-sizing: border-box;
}

.hp-workflow-drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--hp-border-subtle);
}

.hp-workflow-drawer-loading,
.hp-workflow-drawer-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1.5rem;
    text-align: center;
    gap: 0.75rem;
    border: 1px dashed var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    background: rgba(255, 255, 255, 0.02);
}

.hp-workflow-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.hp-workflow-card {
    background: var(--hp-surface-raised);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    padding: 1.25rem;
    display: flex;
    flex-direction: column;
    min-height: 0;
    transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.hp-workflow-card-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    gap: 0.75rem;
}

.hp-workflow-card-top {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    flex-shrink: 0;
}

.hp-workflow-card:hover {
    border-color: var(--hp-primary-light);
    box-shadow: var(--hp-shadow-md);
    transform: translateY(-1px);
}

.hp-workflow-highlight {
    border-color: var(--hp-primary);
    box-shadow: 0 0 0 1px var(--hp-primary);
}

.hp-workflow-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.hp-workflow-title {
    color: var(--hp-text);
    font-weight: 600;
}

.hp-workflow-card-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    font-size: var(--hp-font-2xs);
    margin-top: -0.2rem;
    color: var(--hp-text-muted);
}

.hp-workflow-card-meta .rzi {
    font-size: 0.85rem !important;
}

.hp-workflow-stages-region {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    min-width: 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-workflow-stages-list {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

.hp-workflow-stages-more {
    display: block;
    width: 100%;
    margin: 0;
    padding: 0.35rem 0.6rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    font-size: var(--hp-font-2xs);
    font-weight: 500;
    line-height: 1.35;
    color: var(--hp-text-muted);
    text-align: left;
    cursor: pointer;
    transition: color 0.15s ease, background 0.15s ease;
}

button.hp-workflow-stages-more:hover {
    color: var(--hp-primary-accent);
    background: rgba(255, 255, 255, 0.04);
}

.hp-workflow-stage {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: var(--hp-font-xs);
    padding: 0.35rem 0.6rem;
    background: rgba(255, 255, 255, 0.03);
    border-radius: var(--hp-radius-sm);
    transition: background 0.15s ease;
}

.hp-workflow-stage:hover {
    background: rgba(255, 255, 255, 0.06);
}

.hp-workflow-stage-name {
    color: var(--hp-text-secondary);
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hp-workflow-stage-link {
    color: var(--hp-primary-accent);
    text-decoration: none;
    font-weight: 500;
}

.hp-workflow-stage-link:hover {
    text-decoration: underline;
}

/* Compact badges sit on raised drawer surfaces where the 10–16% tints land too light for 11px
   text (success 4.03:1, info 4.26:1, warning 4.03:1); the deep well under them clears 4.5:1
   for every severity. */
.hp-badge-compact {
    padding: 0.1rem 0.45rem;
    font-size: 0.6875rem;
    border-radius: 4px;
    font-weight: 600;
    background: var(--hp-bg-deepest);
}

.hp-workflow-card-summary {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-secondary);
    background: rgba(255, 255, 255, 0.03);
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    margin-top: -0.25rem;
    min-width: 0;
}

.hp-workflow-card-summary > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-workflow-drawer-header-text {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.hp-workflow-drawer-all-link,
.hp-workflow-drawer-all-link .rz-link-text {
    font-size: var(--hp-font-xs);
    /* The drawer portals outside the shell; Radzen's own link colour (2.96:1) won here. */
    color: var(--hp-primary-accent);
}

/* The slide-out-on-hover edge tabs depend on hover; on touch they are just two unlabeled
   slivers overlapping the content edge. Fingers get round, fully visible buttons instead. */
@media (max-width: 1024px), (pointer: coarse) {
    .hp-workflow-drawer-toggle,
    .hp-feedback-drawer-toggle {
        top: auto;
        right: 1rem;
        transform: none;
        width: 2.75rem;
        height: 2.75rem;
        padding: 0;
        justify-content: center;
        border-right: 1px solid var(--hp-border);
        border-radius: var(--hp-radius-pill);
    }

    .hp-workflow-drawer-toggle {
        bottom: 4.5rem;
    }

    .hp-feedback-drawer-toggle {
        bottom: 1rem;
    }

    .hp-workflow-drawer-toggle:hover,
    .hp-feedback-drawer-toggle:hover {
        transform: none;
    }

    .hp-workflow-drawer-toggle > span,
    .hp-feedback-drawer-toggle > span {
        display: none;
    }

    .hp-feedback-drawer-toggle-unread::after {
        position: absolute;
        top: 0.15rem;
        right: 0.15rem;
    }
}

.hp-feedback-drawer-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--hp-border-subtle);
}

.hp-feedback-drawer-header-text {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.hp-feedback-drawer-history {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-feedback-drawer-loading {
    display: flex;
    justify-content: center;
    padding: 1rem;
}

/* The ticket register borrows the service-registry row grammar; the drawer is narrower than the
   dashboard grid, so the subject takes the flexible space instead of the relationship sentence. */
.hp-ticket-registry .hp-svc-name {
    width: auto;
    flex: 1 1 45%;
}

.hp-ticket-registry .hp-svc-rel {
    flex: 0 1 auto;
}

.hp-ticket-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
}

.hp-ticket-attach-button {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    align-self: flex-start;
    padding: 0.4rem 0.75rem;
    border: 1px dashed var(--hp-border);
    border-radius: var(--hp-radius);
    color: var(--hp-text-secondary);
    font-size: var(--hp-font-sm);
    cursor: pointer;
}

.hp-ticket-attach-button:hover {
    border-color: var(--hp-primary);
    color: var(--hp-text);
}

/* The native file input stretches invisibly over the whole control so it stays keyboard-focusable
   and click-forwarding without a JS proxy. */
.hp-ticket-attach-button input[type="file"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}

.hp-ticket-attach-button:focus-within {
    outline: 2px solid var(--hp-primary);
    outline-offset: 2px;
}

.hp-ticket-meta {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.hp-ticket-meta-res {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
}

.hp-ticket-closed-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    letter-spacing: 0.15em;
    text-transform: uppercase;
}

.hp-feedback-drawer-toggle-unread::after {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--hp-radius-round);
    background: var(--hp-success);
    flex-shrink: 0;
}

.hp-ticket-thread {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-height: 50vh;
    overflow-y: auto;
    padding-right: 0.25rem;
}

.hp-ticket-message {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.75rem;
    border-radius: var(--hp-radius-sm);
    border: 1px solid var(--hp-border-subtle);
}

.hp-ticket-message-customer {
    background: rgba(255, 255, 255, 0.03);
}

.hp-ticket-message-staff {
    background: rgba(110, 146, 192, 0.12);
    border-color: rgba(110, 146, 192, 0.35);
}

.hp-ticket-message-body {
    white-space: pre-wrap;
    word-break: break-word;
}

.hp-ticket-attachment-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border-subtle);
    background: rgba(255, 255, 255, 0.04);
    color: inherit;
    font-size: 0.8rem;
    cursor: pointer;
}

.hp-ticket-attachment-chip:hover {
    border-color: var(--hp-primary-accent);
}

.hp-ticket-attachment-chip .rzi {
    font-size: var(--hp-font-md);
}

.hp-workflow-title-link {
    color: inherit;
    text-decoration: none;
}

.hp-workflow-title-link:hover {
    color: var(--hp-primary-accent);
    text-decoration: underline;
}

.hp-workflow-status-message > span {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

.hp-workflow-status-message {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-secondary);
    line-height: 1.4;
    padding: 0.5rem;
    background: rgba(255, 255, 255, 0.02);
    border-radius: 4px;
}

.hp-workflow-status-message.hp-status-error {
    background: color-mix(in srgb, var(--hp-danger) 5%, transparent);
    color: var(--hp-danger-light);
    border: 1px solid color-mix(in srgb, var(--hp-danger) 10%, transparent);
}

.hp-workflow-card-actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: auto;
    flex-shrink: 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-workflow-card-actions:not(.hp-workflow-card-actions-stacked) .rz-button {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    white-space: nowrap;
}

.hp-workflow-card-actions-stacked {
    flex-direction: column;
    align-items: stretch;
    gap: 0.625rem;
}

.hp-workflow-card-actions-stacked .rz-button {
    width: 100%;
    justify-content: center;
}.hp-mono {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
}

.hp-access-ref,
.hp-access-endpoints {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.hp-access-ref-label,
.hp-access-endpoint-label {
    display: block;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.hp-access-ref-value,
.hp-access-endpoint-value {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
    color: var(--hp-text);
    word-break: break-all;
}

/* The value wraps inside its own cell; the copy button stays on the first line instead of
   dropping under a long hostname. */
.hp-access-endpoint-value {
    flex: 1 1 auto;
    min-width: 0;
}

.hp-access-endpoint-row {
    display: grid;
    grid-template-columns: minmax(110px, 28%) 1fr;
    gap: 0.75rem 1rem;
    align-items: start;
}

@media (max-width: 640px) {
    .hp-access-endpoint-row {
        grid-template-columns: 1fr;
        gap: 0.35rem;
    }
}

/* Terminal / log viewers */

.hp-terminal {
    background: var(--hp-terminal-bg);
    color: var(--hp-terminal-text);
    border: 1px solid var(--hp-terminal-border);
    border-radius: var(--hp-radius-sm);
    padding: 1rem;
    overflow-y: auto;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-sm);
    min-height: 320px;
    max-height: 480px;
}

.hp-terminal.hp-terminal-tall {
    min-height: unset;
    max-height: unset;
    height: 500px;
    font-size: 0.9rem;
}

/* On a 667px-tall phone the fixed heights leave no page behind the log viewer. */
@media (max-width: 640px) {
    .hp-terminal {
        min-height: 200px;
        max-height: 45dvh;
    }

    .hp-terminal.hp-terminal-tall {
        height: 45dvh;
    }
}

.hp-terminal-text {
    color: var(--hp-terminal-text);
}

.hp-terminal-muted {
    color: var(--hp-terminal-muted);
    font-style: italic;
}

.hp-terminal-line {
    margin-bottom: 0.2rem;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--hp-terminal-text);
}

.hp-terminal-line.hp-terminal-line-spaced {
    margin-bottom: 0.25rem;
}

.hp-terminal-timestamp {
    color: var(--hp-terminal-muted);
}

.hp-terminal-level {
    font-weight: 600;
}

.hp-terminal-level-default {
    color: var(--hp-terminal-text);
}

.hp-terminal-error,
.hp-terminal-line.hp-terminal-error {
    color: var(--hp-terminal-error);
}

.hp-terminal-warn,
.hp-terminal-line.hp-terminal-warn {
    color: var(--hp-terminal-warn);
}

.hp-terminal-info,
.hp-terminal-level.hp-terminal-info {
    color: var(--hp-terminal-info);
}

.hp-terminal-debug,
.hp-terminal-line.hp-terminal-debug {
    color: var(--hp-terminal-muted);
}

.hp-terminal-streaming {
    color: var(--hp-terminal-muted);
    font-style: italic;
    margin-top: 0.5rem;
}

.hp-terminal-loading {
    padding: 2rem;
}

.hp-account-preference-label {
    display: flex;
    gap: 0.65rem;
    align-items: flex-start;
    font-size: 0.95rem;
    color: var(--hp-text-secondary);
    line-height: 1.45;
}

/* A native checkbox: one control with one label, nothing nested inside an interactive role. */
.hp-account-preference-check {
    flex: none;
    width: 1rem;
    height: 1rem;
    margin: 0.2rem 0 0;
    accent-color: var(--hp-primary-accent);
}

.hp-account-preference-check:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.auth-marketing-consent {
    margin-top: 0.35rem;
}

/* Cookie consent banner */

.hp-cookie-consent {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 10000;
    padding: 1rem;
    pointer-events: none;
}

.hp-cookie-consent-inner {
    pointer-events: auto;
    max-width: 56rem;
    margin: 0 auto;
    padding: 1.25rem 1.5rem;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 1.5rem;
    align-items: flex-end;
    justify-content: space-between;
    border-color: var(--hp-border);
    box-shadow: var(--hp-shadow);
}

.hp-cookie-consent-title {
    margin: 0 0 0.35rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--hp-text);
}

.hp-cookie-consent-lead {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--hp-text-secondary);
    max-width: 42rem;
}

.hp-cookie-consent-link {
    color: var(--hp-primary-accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.hp-cookie-consent-link:hover {
    color: var(--hp-primary-light);
}

.hp-cookie-consent-settings {
    margin: 1rem 0 0;
    padding: 0;
    border: 0;
    display: grid;
    gap: 0.65rem;
    width: 100%;
}

.hp-cookie-consent-settings-legend {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--hp-text);
    margin-bottom: 0.35rem;
}

.hp-cookie-consent-option {
    display: flex;
    gap: 0.65rem;
    align-items: flex-start;
    font-size: 0.85rem;
    color: var(--hp-text-secondary);
    cursor: pointer;
}

.hp-cookie-consent-option input {
    margin-top: 0.2rem;
    accent-color: var(--hp-primary);
}

.hp-cookie-consent-option-locked,
.hp-cookie-consent-option-disabled {
    cursor: default;
    opacity: 0.92;
}

.hp-cookie-consent-option-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.hp-cookie-consent-option-title {
    font-weight: 600;
    color: var(--hp-text);
}

.hp-cookie-consent-option-hint {
    color: var(--hp-text-muted);
    line-height: 1.4;
}

.hp-cookie-consent-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    flex-shrink: 0;
}

.hp-cookie-consent-btn {
    border-radius: var(--hp-radius-sm);
    padding: 0.55rem 0.9rem;
    font-size: var(--hp-font-sm);
    font-weight: 600;
    border: 1px solid transparent;
    cursor: pointer;
    font-family: inherit;
}

.hp-cookie-consent-btn-primary {
    background: var(--hp-gradient-primary);
    color: var(--hp-text);
    border-color: rgba(110, 146, 192, 0.45);
}

.hp-cookie-consent-btn-secondary {
    background: var(--hp-surface-overlay);
    color: var(--hp-text);
    border-color: var(--hp-border);
}

.hp-cookie-consent-btn-ghost {
    background: transparent;
    color: var(--hp-text-secondary);
    border-color: transparent;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.hp-cookie-consent-btn:hover {
    filter: brightness(1.05);
}

.hp-cookie-consent-btn:focus-visible {
    outline: 2px solid var(--hp-primary-accent);
    outline-offset: 2px;
}

@media (max-width: 640px) {
    .hp-cookie-consent-inner {
        padding: 1rem;
    }

    .hp-cookie-consent-actions {
        width: 100%;
    }

    .hp-cookie-consent-btn {
        flex: 1 1 auto;
        min-width: 8rem;
    }
}

/* ===== Resource list shell ===== */
/* Empty and error states sit directly on the page background, near the header — not centred
   down the viewport. The centred variant survived only on pages without an Intro fragment,
   which made /apps (tight, via its intro relic) read differently from every sibling. One
   spacing now, the tight one (chrille 2026-08-07). */
.hp-list-blank {
    padding-block: 0.5rem 1rem;
}

.hp-list-blank .hp-empty-state {
    padding-block: 1.25rem;
}

/* ===== Inline forms (HpInlineForm) ===== */
/* No max-width on the field grid: a 64rem measure here left the submit button (right-aligned on
   the card) hundreds of pixels away from the fields on wide screens, while every other form in the
   product fills its card. Fields and actions share the card edge again. */
.hp-inline-form-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 0.75rem;
    /* start, not end: bottom-aligning cells made any field with a helper button under it shove
       its NEIGHBORS' inputs downward — the fields read as randomly staggered. Inputs share a
       top line; helpers hang below their own field only. */
    align-items: start;
}

/* A field plus its inline helper (e.g. "Enter a subject manually"), stacked and top-aligned. */
.hp-grant-field {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
}

.hp-grant-field .rz-form-field {
    width: 100%;
}

.hp-inline-form-fields .hp-inline-form-full {
    grid-column: 1 / -1;
}

/* A checkbox and its label are one unit: RadzenCheckBox and RadzenLabel are siblings, so in a
   wrapping row the label used to break away from its box onto the next line. */
.hp-check-field {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    white-space: nowrap;
}

.hp-check-group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.5rem;
    min-height: 2.5rem;
}

/* ===== Pending changes (restart required) banner ===== */
.hp-pending-changes-banner {
    width: 100%;
}

.hp-pending-changes-list {
    margin: 0;
    padding-left: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.hp-pending-changes-list code {
    font-size: var(--hp-font-xs);
    margin-right: 0.5rem;
}

/* Prose column for legal/document pages. Replaces the inline max-width the four legal pages
   each carried, so the measure is set in one place and works under both the app shell and the
   anonymous shell. */
.hp-page-prose {
    max-width: 48rem;
    margin-inline: auto;
}

/* Flexible capacity picker (FlexiblePlanSizePicker). Each dimension pairs a slider with a typed
   value so narrow plan ranges stay usable, carries its own share of the quoted monthly cost, and
   the panel closes with the quote total. Costs use tabular numerals so live re-quotes don't make
   the layout jitter. */

.hp-cap {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.hp-cap-head {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.hp-cap-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--hp-text);
}

.hp-cap-sub {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-cap-rows {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.hp-cap-row {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.85rem 1rem 0.9rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
}

.hp-cap-row-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
}

.hp-cap-dim {
    font-size: var(--hp-font-sm);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-cap-row-cost {
    font-size: var(--hp-font-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--hp-text-secondary);
    white-space: nowrap;
}

.hp-cap-row-cost--included {
    color: var(--hp-success);
}

.hp-cap-controls {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}

.hp-cap-track {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    /* The handle is centred on its value, so at either end half of it sits outside the track.
       Insetting the track keeps it clear of the row's edge instead of clipping against it. */
    padding-inline: 0.6rem;
}

/* Radzen ships a tall, narrow bar of a handle that reads as a scrollbar thumb rather than something
   to grab. Retuning its own variables keeps every positioning rule Radzen computes from them. */
.hp-cap-track {
    --rz-slider-horizontal-height: 0.375rem;
    --rz-slider-handle-width: 1.15rem;
    --rz-slider-handle-height: 1.15rem;
    --rz-slider-handle-border-radius: var(--hp-radius-round);
    --rz-slider-background-color: var(--hp-border-subtle);
    --rz-slider-border: 1px solid transparent;
    --rz-slider-handle-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    --rz-slider-handle-hover-shadow: 0 0 0 4px var(--hp-primary-muted);
}

/* The handle stands taller than the track it rides on, so the track needs room above and below or
   the handle crowds the row's label and the scale beneath it. */
.hp-cap-track .rz-slider {
    margin-block: 0.4rem;
}

.hp-cap-scale {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    font-size: var(--hp-font-2xs);
    font-variant-numeric: tabular-nums;
    color: var(--hp-text-muted);
}

.hp-cap-input {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.hp-cap-input .rz-spinner {
    width: 7rem;
}

.hp-cap-unit {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
    min-width: 2.75rem;
}

.hp-cap--pending .hp-cap-row-cost {
    animation: hp-cap-pulse 1.2s ease-in-out infinite;
}

@keyframes hp-cap-pulse {
    50% { opacity: 0.45; }
}

@media (prefers-reduced-motion: reduce) {
    .hp-cap--pending .hp-cap-row-cost {
        animation: none;
        opacity: 0.6;
    }
}

@media (max-width: 640px) {
    .hp-cap-controls {
        flex-wrap: wrap;
        gap: 0.75rem;
    }

    .hp-cap-track {
        flex-basis: 100%;
    }

    .hp-cap-input {
        margin-inline-start: auto;
    }
}

.hp-cap-presets {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.hp-cap-presets-label {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    margin-inline-end: 0.1rem;
}

.hp-cap-preset {
    appearance: none;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-pill);
    background: var(--hp-surface-muted);
    color: var(--hp-text-secondary);
    font: inherit;
    font-size: var(--hp-font-2xs);
    font-weight: 600;
    padding: 0.25rem 0.7rem;
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
}

.hp-cap-preset:hover:not(:disabled) {
    border-color: var(--hp-primary);
    color: var(--hp-text);
}

.hp-cap-preset:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-cap-preset--active {
    background: var(--hp-primary-muted);
    border-color: var(--hp-primary);
    color: var(--hp-primary-accent);
}

.hp-cap-preset:disabled {
    cursor: default;
    opacity: 0.6;
}

.hp-cap-preset-hint {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    margin-top: -0.5rem;
}

/* Quote totals in review steps — replaces the per-flow inline var(--rz-primary) styles. */
.hp-quote-total {
    color: var(--hp-primary-accent);
    font-variant-numeric: tabular-nums;
}

/* Shared estimated-cost block (QuoteTotal). Figures read top-down in one order everywhere: the
   monthly total, what that is including VAT, and last the split it is made of. */

.hp-quote-summary {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
    background: var(--hp-surface-muted);
}

.hp-quote-summary--flat {
    padding: 0;
    border: none;
    background: none;
}

.hp-quote-summary-label {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-quote-summary-placeholder {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-quote-summary-figures {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.2rem;
    text-align: end;
}

.hp-quote-summary-value {
    font-size: var(--hp-font-lg);
    font-weight: 700;
    color: var(--hp-primary-accent);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-quote-summary-vat {
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--hp-text-muted);
    letter-spacing: 0.02em;
    margin-inline-start: 0.3rem;
}

.hp-quote-summary-incl {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-quote-summary-breakdown {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    font-variant-numeric: tabular-nums;
}

.hp-quote-summary-sep {
    margin-inline: 0.35rem;
    opacity: 0.6;
}

.hp-quote-summary--pending .hp-quote-summary-value,
.hp-quote-summary--pending .hp-quote-summary-incl,
.hp-quote-summary--pending .hp-quote-summary-breakdown {
    animation: hp-cap-pulse 1.2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .hp-quote-summary--pending .hp-quote-summary-value,
    .hp-quote-summary--pending .hp-quote-summary-incl,
    .hp-quote-summary--pending .hp-quote-summary-breakdown {
        animation: none;
        opacity: 0.6;
    }
}

@media (max-width: 560px) {
    .hp-quote-summary {
        flex-direction: column;
        align-items: stretch;
    }

    .hp-quote-summary-figures {
        align-items: flex-start;
        text-align: start;
    }
}

/* Free-by-decision meters advertised beside a price (free egress, free backups). */
.hp-free-highlights {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: var(--hp-font-2xs);
    font-weight: 500;
    color: var(--hp-success);
}

.hp-free-highlights .rzi {
    font-size: 0.9375rem;
}

/* Security findings — one row per advisory. The id is monospaced because CVE identifiers are
   scanned character by character and compared against issue trackers, not read as prose. */
.hp-finding-row {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: 6px;
    background: var(--hp-surface-muted);
}

.hp-finding-id {
    font-family: var(--hp-font-mono);
    font-weight: 600;
}

/* The fixed version is the only actionable token in the row, so it carries the one colour that
   says "do this" rather than "this is bad". */
.hp-finding-fix {
    font-family: var(--hp-font-mono);
    color: var(--hp-success);
}

/* Month cost ledger — the usage page's spine. One bar carries two facts on the same 0–100 scale:
   the fill is money already accrued as a share of the projected month-end subtotal, the tick is
   where today sits in the billing month. Their divergence is the point (fill ahead of the tick =
   front-loaded spend; behind = ramping usage), so neither is decoration. */

/* Credit pools: one row per credit the customer holds. The row reads as a sentence —
   amount, where it spends, when it expires — because a shared pool scoped to several
   services must never look like a per-service balance. */
.hp-credit-pools {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.hp-credit-pool {
    display: flex;
    align-items: baseline;
    gap: 0.35rem 0.75rem;
    flex-wrap: wrap;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--hp-border-subtle);
    border-left: 2px solid var(--hp-primary);
    border-radius: 0.5rem;
}

.hp-credit-pool-amount {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--hp-text);
    font-variant-numeric: tabular-nums;
}

.hp-credit-pool-scope {
    font-size: var(--hp-font-sm);
    color: var(--hp-text);
}

.hp-credit-pool-expiry {
    margin-left: auto;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    white-space: nowrap;
}

@media (max-width: 640px) {
    .hp-credit-pool-expiry {
        margin-left: 0;
        flex-basis: 100%;
    }
}

.hp-month-ledger {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.hp-month-ledger-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem 2rem;
    flex-wrap: wrap;
}

.hp-month-ledger-title {
    margin: 0;
    font-size: var(--hp-font-md);
    font-weight: 600;
    color: var(--hp-text);
}

.hp-month-ledger-caption {
    margin: 0.15rem 0 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-month-ledger-total {
    text-align: right;
}

.hp-month-ledger-total-label {
    margin: 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-month-ledger-total-value {
    margin: 0.1rem 0 0;
    font-size: var(--hp-font-3xl);
    font-weight: 700;
    line-height: 1.15;
    color: var(--hp-primary-accent);
    font-variant-numeric: tabular-nums;
}

.hp-month-ledger-total-hint {
    margin: 0.15rem 0 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-month-ledger-bar {
    position: relative;
    height: 0.875rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border-subtle);
    /* Stripes on the whole track; the solid fill paints over the accrued part, so the visible
       striping is exactly the projected remainder without a second positioned element. */
    background: repeating-linear-gradient(
        -55deg,
        var(--hp-primary-muted) 0 6px,
        transparent 6px 12px
    );
    /* Headroom for the "today" label below the track. */
    margin-bottom: 1.1rem;
}

.hp-month-ledger-fill {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: var(--hp-radius-pill);
    background: var(--hp-primary);
    transition: width 300ms ease;
}

.hp-month-ledger-today {
    position: absolute;
    top: -0.3rem;
    bottom: -0.3rem;
    width: 2px;
    margin-left: -1px;
    background: var(--hp-text);
}

.hp-month-ledger-today-label {
    position: absolute;
    top: calc(100% + 0.15rem);
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.6875rem;
    color: var(--hp-text-muted);
    white-space: nowrap;
}

/* Keep the label inside the card when today sits at either end of the month. */
.hp-month-ledger-today[style*="left: 0%"] .hp-month-ledger-today-label,
.hp-month-ledger-today[style*="left: 1%"] .hp-month-ledger-today-label {
    transform: none;
    left: 0;
}

.hp-month-ledger-today[style*="left: 100%"] .hp-month-ledger-today-label,
.hp-month-ledger-today[style*="left: 99"] .hp-month-ledger-today-label {
    transform: none;
    left: auto;
    right: 0;
}

.hp-month-ledger-figures {
    display: flex;
    align-items: baseline;
    gap: 0.75rem 1rem;
    flex-wrap: wrap;
}

.hp-month-ledger-figure-label {
    margin: 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.hp-month-ledger-figure-value {
    margin: 0.1rem 0 0;
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--hp-text);
    font-variant-numeric: tabular-nums;
}

.hp-month-ledger-figure-op {
    font-size: var(--hp-font-md);
    color: var(--hp-text-muted);
    align-self: center;
}

.hp-ledger-swatch {
    width: 0.625rem;
    height: 0.625rem;
    border-radius: 2px;
    display: inline-block;
}

.hp-ledger-swatch-accrued {
    background: var(--hp-primary);
}

.hp-ledger-swatch-projected {
    background: repeating-linear-gradient(
        -55deg,
        var(--hp-primary-muted) 0 3px,
        transparent 3px 6px
    );
    border: 1px solid var(--hp-border-subtle);
}

.hp-month-ledger-footnote {
    margin: 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

@media (max-width: 640px) {
    .hp-month-ledger-total {
        text-align: left;
    }
}

@media (prefers-reduced-motion: reduce) {
    .hp-month-ledger-fill {
        transition: none;
    }
}

/* Included-allowance meter — the ledger bar's grammar at resource scale: solid = included usage
   consumed, capped at 100% so overage never stretches the track; overage is stated as its own
   figure in warning colour instead. */

.hp-allowance-meter {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.hp-allowance-meter-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem 1rem;
    flex-wrap: wrap;
    font-size: var(--hp-font-xs);
}

.hp-allowance-meter-metric {
    color: var(--hp-text-secondary);
    font-weight: 500;
}

.hp-allowance-meter-figures {
    color: var(--hp-text-muted);
    font-variant-numeric: tabular-nums;
}

.hp-allowance-meter-track {
    height: 0.5rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border-subtle);
    background: var(--hp-surface-muted);
    overflow: hidden;
}

.hp-allowance-meter-fill {
    height: 100%;
    border-radius: var(--hp-radius-pill);
    background: var(--hp-primary);
}

.hp-allowance-meter-full .hp-allowance-meter-fill {
    background: var(--hp-warning);
}

.hp-allowance-meter-overage {
    font-size: var(--hp-font-2xs);
    color: var(--hp-warning);
    font-variant-numeric: tabular-nums;
}

/* Function cost meter — the allowance meter's grammar with the spend cap on the same track: solid =
   accrued, translucent same-hue = projected remainder (an estimate, so it must read lighter than
   fact), ticks mark the plan's included allowance and the SR-22 spend cap. The track is scaled to
   the largest of cap/projection/accrued, so the cap tick always sits inside it. Every tick is
   restated as text next to the meter — identity is never colour-alone. */

.hp-fn-cost-meter {
    position: relative;
    height: 0.5rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border-subtle);
    background: var(--hp-surface-muted);
}

.hp-fn-cost-meter-accrued {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    border-radius: var(--hp-radius-pill);
    background: var(--hp-primary);
}

.hp-fn-cost-meter-projected {
    position: absolute;
    top: 0;
    bottom: 0;
    background: var(--hp-primary);
    opacity: 0.35;
}

.hp-fn-cost-meter-tick {
    position: absolute;
    top: -0.2rem;
    bottom: -0.2rem;
    width: 2px;
    margin-left: -1px;
}

.hp-fn-cost-meter-tick-allowance {
    background: var(--hp-text-muted);
}

.hp-fn-cost-meter-tick-cap {
    background: var(--hp-danger);
}

/* Resource cost rows on the usage tab — one header line per resource: name, state, plan, and the
   accrued → projected pair in the ledger's order. */

.hp-usage-resource-head {
    display: flex;
    align-items: center;
    gap: 0.5rem 0.75rem;
    flex-wrap: wrap;
}

.hp-usage-resource-name {
    font-weight: 600;
    color: var(--hp-text);
}

.hp-usage-resource-figures {
    margin-left: auto;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

@media (max-width: 640px) {
    .hp-usage-resource-figures {
        margin-left: 0;
        text-align: left;
        flex-basis: 100%;
    }
}

/* Upcoming-invoice totals — laid out like the paper invoice it becomes: lines above, then this
   column of Subtotal → Credits → VAT → Rounding → Total, right-aligned as on the PDF. */

.hp-invoice-totals {
    margin-left: auto;
    width: 100%;
    max-width: 24rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.hp-invoice-totals-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    font-size: var(--hp-font-sm);
    color: var(--hp-text-secondary);
}

.hp-invoice-totals-row .hp-invoice-totals-amount {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-invoice-totals-row-muted {
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-invoice-totals-row-credit .hp-invoice-totals-amount {
    color: var(--hp-success);
}

.hp-invoice-totals-row-total {
    border-top: 1px solid var(--hp-border);
    padding-top: 0.5rem;
    margin-top: 0.15rem;
    font-size: var(--hp-font-md);
    font-weight: 700;
    color: var(--hp-text);
}

/* Command palette (Ctrl+K). Ported from Cupo's cu-palette, re-tokened for Hostport.
   z-index sits above the drawers (1300-1310) and below the skip link. */
.hp-palette-scrim {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 10vh 1rem 1rem;
    background: rgba(27, 38, 52, 0.6);
}

.hp-palette {
    display: flex;
    flex-direction: column;
    width: min(42rem, 100%);
    max-height: min(32rem, 70vh);
    overflow: hidden;
    background: var(--hp-surface);
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-radius-lg);
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
}

.hp-palette-field {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--hp-border);
}

.hp-palette-field .rzi { color: var(--hp-text-muted); }

.hp-palette-field input {
    flex: 1;
    min-width: 0;
    border: none;
    background: none;
    font: inherit;
    font-size: var(--hp-font-lg);
    color: var(--hp-text);
}

.hp-palette-field input:focus { outline: none; }
.hp-palette-field input::placeholder { color: var(--hp-text-muted); }

.hp-palette-results {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem 0;
}

.hp-palette-group + .hp-palette-group {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-palette-group-title {
    padding: 0.25rem 1rem;
    font-size: var(--hp-font-2xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-palette-row {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    border-inline-start: 2px solid transparent;
    cursor: pointer;
}

.hp-palette-row:hover { background: var(--hp-surface-muted); }

.hp-palette-row.is-active {
    background: var(--hp-surface-muted);
    border-inline-start-color: var(--hp-primary-accent);
}

.hp-palette-row .rzi {
    flex: none;
    margin-top: 2px;
    font-size: 1.1rem;
    color: var(--hp-text-muted);
}

.hp-palette-row-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.hp-palette-row-title { font-weight: 600; }

.hp-palette-row-sub {
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-palette-none {
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--hp-text-muted);
}

.hp-palette-foot {
    display: flex;
    gap: 1rem;
    padding: 0.5rem 1rem;
    border-top: 1px solid var(--hp-border);
    background: var(--hp-surface-muted);
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-palette-foot kbd {
    padding: 0 0.25rem;
    margin-right: 2px;
    font-family: var(--hp-font-mono);
    background: var(--hp-surface);
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-radius-sm);
}

/* Comp 18's header speaks quietly: search is mono text ("Ctrl K search"), not a pill. */
.hp-header-search {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.4rem;
    border: none;
    background: transparent;
    color: var(--hp-text-disabled);
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-2xs);
    cursor: pointer;
}

.hp-header-search:hover { color: var(--hp-text); }

.hp-header-search .rzi { font-size: var(--hp-font-md); }

.hp-header-search kbd {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-3xs);
    padding: 0 0.25rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-sm);
}

@media (max-width: 900px) {
    .hp-header-search span, .hp-header-search kbd { display: none; }
    .hp-header-search { min-width: 2.5rem; min-height: 2.5rem; justify-content: center; }
}

/* Live-status chip: the header's liveness signal for the push-only portal. */
.hp-live-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border-subtle);
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
    white-space: nowrap;
}

.hp-live-chip .hp-live-dot {
    width: 0.45rem;
    height: 0.45rem;
    border-radius: var(--hp-radius-round);
    background: var(--hp-text-muted);
}

.hp-live-chip.is-live .hp-live-dot { background: var(--hp-success); }
.hp-live-chip.is-offline { border-color: rgba(240, 180, 41, 0.42); color: var(--hp-warning); }
.hp-live-chip.is-offline .hp-live-dot { background: var(--hp-warning); }

@media (max-width: 900px) {
    .hp-live-chip .hp-live-label { display: none; }
}

/* The portal's disclosure: a quiet toggle that reveals its own body. Sized to sit inside an alert
   without drawing a box of its own — the thing it replaced (a collapsed RadzenFieldset) drew a
   full-width rule across whatever contained it. */
.hp-disclosure-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.5rem 0.3rem 0.35rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text-secondary);
    font: inherit;
    font-size: var(--hp-font-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.hp-disclosure-toggle:hover {
    background: var(--hp-surface-hover);
    color: var(--hp-text);
}

.hp-disclosure-toggle .rzi,
.hp-disclosure-toggle .rz-icon {
    font-size: var(--hp-font-md) !important;
    opacity: 0.75;
}

.hp-disclosure-body {
    padding-top: 0.5rem;
}

/* Dashboard: stat strip + tap-through rows of running things. */
.hp-dashboard-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--hp-space-4);
}

.hp-dashboard-row {
    display: flex;
    align-items: center;
    gap: var(--hp-space-3);
    width: 100%;
    padding: 0.65rem var(--hp-space-4);
    border: none;
    border-bottom: 1px solid var(--hp-border-subtle);
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.hp-dashboard-row:last-child { border-bottom: none; }
.hp-dashboard-row:hover { background: var(--hp-surface-muted); }

.hp-dashboard-row-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}

.hp-dashboard-row-sub {
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
    white-space: nowrap;
}

.hp-dashboard-row-more .hp-dashboard-row-title {
    color: var(--hp-primary-accent);
    font-weight: 500;
}

/* The header "New" menu opens from the right edge; without this it would overflow the viewport. */
/* ── Workspace shell: rail + context bar ──────────────────────────────────────────────────
   The rail is the portal's one browsable surface (HpWorkspaceNav); the context bar is the
   route-derived breadcrumb and resource switcher (HpContextBar). Both sit INSIDE .hostport-main,
   which is the scroll container, so `position: sticky; top: 0` pins them under the app header
   rather than under the viewport. */

/* Stretch, not flex-start: the rail's sticky positioning needs a wrapper as tall as the shell,
   or there is nothing for it to slide within and it simply scrolls away. */
.hp-shell {
    display: flex;
    align-items: stretch;
    min-height: 100%;
    width: 100%;
}

.hp-shell-rail {
    flex-shrink: 0;
    /* The column carries the full-height deep ground; the rail inside pins to the viewport.
       (Backgrounding the rail itself forced it to content height, and a sticky element as tall
       as the scroll range never sticks — the nav scrolled away with the page.) */
    background: var(--hp-bg-deepest);
    border-right: 1px solid var(--hp-border-subtle);
}

.hp-shell-main {
    flex: 1;
    min-width: 0;
    padding: 1.875rem 2.625rem;
}

@media (max-width: 768px) {
    .hp-shell-main {
        padding: 1rem;
    }

    /* A fixed-layout Radzen table is wider than a phone; the card clipped its last columns
       silently. Scroll the table's own scrollport instead. */
    .hostport-layout .rz-data-grid-data {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

.hp-rail {
    position: sticky;
    top: 0;
    align-self: flex-start;
    display: flex;
    flex-direction: column;
    width: 13.75rem;
    flex-shrink: 0;
    height: calc(100vh - 3.5rem);
    padding: 1rem 1.1rem 0;
    box-sizing: border-box;
    background: transparent;
    transition: width 0.15s ease;
}

.hp-rail-collapsed {
    width: 3.75rem;
    padding-inline: 0.5rem;
}

.hp-rail-scroll {
    flex: 1;
    overflow-y: auto;
    scrollbar-width: thin;
}

.hp-rail-section + .hp-rail-section {
    margin-top: 1.15rem;
}

.hp-rail-section-title {
    padding: 0 0 0.45rem;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-rail-font-label);
    font-weight: 400;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--hp-text-disabled);
}

.hp-rail-collapsed .hp-rail-section-title {
    display: none;
}

.hp-rail-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.32rem 0;
    color: var(--hp-text-muted);
    text-decoration: none;
    font-size: var(--hp-sk-font-row);
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
}

.hp-rail-label {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Inset, because the rail's own scroll container clips anything drawn outside the row. */
.hp-rail-link:focus-visible {
    outline-offset: -2px;
}

/* Comp 18's nav is text, not icon rows — icons only exist for the collapsed rail. */
.hp-rail:not(.hp-rail-collapsed) .hp-rail-link .rzi {
    display: none;
}

.hp-rail-link .rzi {
    font-size: var(--hp-font-lg);
    flex-shrink: 0;
    color: var(--hp-text-muted);
}

.hp-rail-link:hover {
    color: var(--hp-text);
}

.hp-rail-link:hover .rzi {
    color: var(--hp-text);
}

.hp-rail-link.is-active {
    background: transparent;
    color: var(--hp-primary-accent);
}

.hp-rail-link.is-active .rzi {
    color: var(--hp-primary-accent);
}

/* The marker keeps the active row legible when colour alone is not available to the reader. */
.hp-rail-link.is-active::before {
    content: "";
    position: absolute;
    inset-block: 0.35rem;
    inset-inline-start: -1.1rem;
    width: 2px;
    border-radius: var(--hp-radius-pill);
    background: var(--hp-primary-accent);
}

.hp-rail-count {
    margin-inline-start: auto;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-rail-font-label);
    font-weight: 400;
    color: var(--hp-text-muted);
    font-variant-numeric: tabular-nums;
}

.hp-rail-collapsed .hp-rail-count {
    display: none;
}

.hp-rail-sublink {
    padding-inline-start: 1.1rem;
    font-size: var(--hp-font-xs);
    font-weight: 400;
}

.hp-rail-resource .hp-rail-pin-mark {
    margin-inline-start: auto;
    font-size: var(--hp-font-xs) !important;
    opacity: 0.65;
}

.hp-rail-collapsed .hp-rail-label {
    display: none;
}

.hp-rail-collapsed .hp-rail-link {
    justify-content: center;
    padding-inline: 0;
}

.hp-rail-collapse {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    width: 100%;
    padding: 0.6rem 0.65rem;
    margin-top: 0.5rem;
    border: none;
    border-top: 1px solid var(--hp-border-subtle);
    background: transparent;
    color: var(--hp-text-muted);
    font: inherit;
    font-size: var(--hp-font-xs);
    cursor: pointer;
}

.hp-rail-collapse:hover {
    color: var(--hp-text);
}

.hp-rail-collapsed .hp-rail-collapse {
    justify-content: center;
}

.hp-nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border: 1px solid transparent;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text-secondary);
    cursor: pointer;
}

.hp-nav-toggle:hover {
    color: var(--hp-text);
    border-color: var(--hp-border);
}

.hp-rail-backdrop {
    display: none;
}

/* Below 1024px the rail becomes an off-canvas drawer: at that width a 15rem rail leaves the
   content column narrower than the tables it has to hold. */
@media (max-width: 1024px) {
    .hp-nav-toggle {
        display: inline-flex;
    }

    .hp-shell-rail {
        position: fixed;
        inset-block: 3.5rem 0;
        inset-inline-start: 0;
        z-index: 1090;
        transform: translateX(-100%);
        visibility: hidden;
        transition: transform 0.24s cubic-bezier(0.2, 0, 0, 1), visibility 0s linear 0.24s;
    }

    .hp-shell-rail-open {
        transform: translateX(0);
        visibility: visible;
        transition: transform 0.24s cubic-bezier(0.2, 0, 0, 1);
    }

    .hp-rail {
        width: min(18rem, 85vw);
        max-height: none;
        height: 100%;
        padding-bottom: env(safe-area-inset-bottom, 0);
        background: var(--hp-surface);
        border-right: 1px solid var(--hp-border);
        box-shadow: var(--hp-shadow-md);
    }

    /* A collapsed drawer makes no sense — the drawer is already hidden when it is not wanted. */
    .hp-rail-collapsed {
        width: min(18rem, 85vw);
    }

    .hp-rail-collapsed .hp-rail-label,
    .hp-rail-collapsed .hp-rail-section-title,
    .hp-rail-collapsed .hp-rail-org .hp-org-chip-name,
    .hp-rail-collapsed .hp-rail-org .hp-rail-org-chevron {
        display: revert;
    }

    .hp-rail-collapse {
        display: none;
    }

    .hp-rail-backdrop {
        display: block;
        position: fixed;
        inset-block: 3.5rem 0;
        inset-inline: 0;
        z-index: 1080;
        background: color-mix(in srgb, var(--hp-bg-deepest) 62%, transparent);
        backdrop-filter: blur(2px);
        animation: hp-backdrop-in 0.24s cubic-bezier(0.2, 0, 0, 1);
    }
}

@keyframes hp-backdrop-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.hp-crumbs {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--hp-font-xs);
    min-width: 0;
}

.hp-crumb {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.4rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text-muted);
    text-decoration: none;
    font: inherit;
    font-size: var(--hp-font-xs);
    max-width: 18rem;
    cursor: pointer;
}

.hp-crumb:hover {
    color: var(--hp-text);
    background: var(--hp-surface-overlay);
}

.hp-crumb-sep {
    font-size: var(--hp-font-sm) !important;
    color: var(--hp-text-muted);
    opacity: 0.6;
}

.hp-crumb-current {
    color: var(--hp-text);
    font-weight: 600;
}

.hp-crumb-current:disabled {
    cursor: default;
    background: transparent;
}

.hp-crumb-current-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-crumb-switch-icon {
    font-size: var(--hp-font-sm) !important;
    opacity: 0.7;
}

/* Deliberately no top/left, and nothing between the menu and the header may be positioned: the
   trail clips (overflow: hidden on .hp-header-crumbs), and a clip reaches every absolutely
   positioned box whose containing block sits inside it. Anchored to the switcher, the menu opened
   below the trail's box, clipped to nothing, while its backdrop swallowed the next click. Its
   containing block is the sticky header instead, and its static position keeps it under the
   trigger. */
.hp-crumb-menu {
    position: absolute;
    margin-top: 0.35rem;
    z-index: 1200;
    width: min(320px, calc(100vw - 2rem));
    max-height: 60vh;
    overflow-y: auto;
    /* The trail's nowrap is inherited; a long app name would scroll the menu sideways. */
    white-space: normal;
    overflow-wrap: anywhere;
}

.hp-crumb-menu-note {
    padding: 0.75rem 1rem;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
}

.hp-crumb-pin {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin-inline-start: 0.25rem;
    border: none;
    border-radius: var(--hp-radius-sm);
    background: transparent;
    color: var(--hp-text-muted);
    cursor: pointer;
}

.hp-crumb-pin .rzi {
    font-size: var(--hp-font-md);
}

.hp-crumb-pin:hover {
    color: var(--hp-text);
    background: var(--hp-surface-overlay);
}

.hp-crumb-pin.is-pinned {
    color: var(--hp-primary-accent);
}

/* In the header's start column the trail must lose gracefully to the fixed columns beside it:
   section crumbs collapse away on narrow screens and only the current resource survives,
   truncated — never a second row, never a pushed-out search box. */
.hp-header-crumbs {
    overflow: hidden;
    white-space: nowrap;
    flex: 1;
    margin-inline-start: 0.25rem;
    /* The wordmark's baseline sits low inside the logo PNG; without this nudge the trail
       reads as floating above it even though both boxes are flex-centered. */
    margin-top: 2px;
}

.hp-header-crumbs .hp-crumb {
    font-size: var(--hp-font-sm);
}

@media (max-width: 900px) {
    .hp-header-crumbs .hp-crumb:not(.hp-crumb-current):not(.hp-crumb-leaf),
    .hp-header-crumbs .hp-crumb-sep:not(:has(+ .hp-crumb-switcher)):not(:has(+ .hp-crumb-leaf)) {
        display: none;
    }
}

@media (max-width: 640px) {
    .hp-header-crumbs {
        display: none;
    }
}

/* ==========================================================================
   Systemkarta map (HpSystemMap) — comp 18/19 grammar. Zero new literals: colors
   through color-mix() over tokens, sizes through --hp-map-* tokens. The server places
   glyphs; hostportMap (app.js) draws the lines from measured rectangles, so the line
   layer stays invisible until it has measured — no line is ever seen through a glyph.
   ========================================================================== */

.hp-map-frame {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

/* A phone cannot hold a band of glyphs with their labels side by side; the map keeps its
   drawing width and pans, like any map, instead of wrapping hostnames into four lines. */
@media (max-width: 640px) {
    .hp-map-frame {
        /* The fade at the right edge is the pan affordance: the drawing continues. */
        mask-image: linear-gradient(to right, black calc(100% - 36px), transparent);
    }

    .hp-map-frame > .hp-map {
        min-width: 640px;
    }
}

.hp-map {
    position: relative;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    overflow: hidden;
    background:
        radial-gradient(circle at 30% 35%, color-mix(in srgb, var(--hp-primary) 7%, transparent), transparent 40%),
        radial-gradient(circle at 82% 45%, color-mix(in srgb, var(--hp-primary) 5%, transparent), transparent 35%),
        radial-gradient(color-mix(in srgb, var(--hp-primary) 7%, transparent) 1px, transparent 1px),
        color-mix(in srgb, var(--hp-bg-deepest) 50%, transparent);
    background-size: auto, auto, 26px 26px, auto;
}

.hp-map-lines {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    transition: opacity 0.4s ease-out;
}

.hp-map.is-measured .hp-map-lines {
    opacity: 1;
}

.hp-map-line {
    fill: none;
    stroke: color-mix(in srgb, var(--hp-primary-accent) 40%, transparent);
    stroke-width: 1.4;
    stroke-linecap: round;
}

.hp-map-line--muted {
    stroke: color-mix(in srgb, var(--hp-primary-accent) 25%, transparent);
}

/* An attachment that leaves its region is a fact worth a different stroke: it costs a
   round trip between sites on every call. */
.hp-map-line--cross {
    stroke-dasharray: 5 4;
}

/* The internet's way in — the cloud to a region, a region to a domain or an exposed service.
   The arrowhead is the mark; a service with no arrow leading to it is not reachable from
   outside. */
.hp-map-line--traffic {
    stroke: color-mix(in srgb, var(--hp-primary-accent) 55%, transparent);
}

.hp-map-arrow path {
    fill: color-mix(in srgb, var(--hp-primary-accent) 55%, transparent);
}

.hp-map-arrow--focus path {
    fill: color-mix(in srgb, var(--hp-warning) 75%, transparent);
}

/* Placement only: the service runs in that region and nothing public reaches it. Dots, so it
   is mistaken neither for traffic nor for an attachment. */
.hp-map-line--place {
    stroke-dasharray: 0.1 4.5;
    stroke-width: 1.8;
}

.hp-map-line.is-focus {
    stroke: color-mix(in srgb, var(--hp-warning) 75%, transparent);
    stroke-width: 2;
}

.hp-map.has-focus .hp-map-line:not(.is-focus) {
    opacity: 0.3;
}

/* The node's anchor is its glyph's center — what the lines aim at — not the center of the
   glyph-plus-label block, so a label hanging below never shifts where a line lands. */
.hp-map-node {
    position: absolute;
    transform: translate(-50%, 0);
}

/* A glyph with a page is a real link: the register row is its accessible twin, so the link
   needs no extra name — its label and meta line are its text. Hover and focus change colour,
   never geometry, because hostportMap measures these boxes for the lines. */
a.hp-map-node {
    color: inherit;
    text-decoration: none;
    border-radius: var(--hp-radius-sm);
}

a.hp-map-node:hover .hp-glyph-name,
a.hp-map-node:focus-visible .hp-glyph-name {
    color: var(--hp-primary-accent);
}

a.hp-map-node:focus-visible {
    outline: 2px solid var(--hp-primary-accent);
    outline-offset: 6px;
}

.hp-map-node .hp-service-glyph {
    margin-top: calc(var(--hp-glyph-scale) * -17px);
    white-space: nowrap;
}

.hp-map-node--hero .hp-service-glyph {
    margin-top: calc(var(--hp-glyph-scale) * -55px);
}

.hp-map-node .hp-glyph-name {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hp-map.has-focus .hp-map-node.is-dimmed {
    opacity: 0.3;
}

.hp-map-zone {
    position: absolute;
    border: 1px dashed color-mix(in srgb, var(--hp-primary) 18%, transparent);
    border-radius: var(--hp-map-zone-radius);
}

.hp-map-zone-label {
    position: absolute;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-zone);
    letter-spacing: 0.22em;
    color: var(--hp-text-muted);
    white-space: nowrap;
}

.hp-map-zone-label b {
    display: block;
    letter-spacing: 0.06em;
    font-weight: 400;
    color: var(--hp-text-disabled);
    font-size: var(--hp-map-font-zone-sub);
    margin-top: 3px;
    text-transform: uppercase;
}

/* Between two region groups inside one project zone. */
.hp-map-divider {
    position: absolute;
    width: 0;
    border-left: 1px dotted color-mix(in srgb, var(--hp-primary) 24%, transparent);
}

/* The delivery chip (comp 19): env-var name on the deep well, amber-tinted border. Placed by
   hostportMap on the line's longest clear run; hidden until it has a place. */
.hp-map-chip {
    position: absolute;
    transform: translate(-50%, -50%);
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-chip);
    color: var(--hp-attachment-label);
    background: color-mix(in srgb, var(--hp-bg-deepest) 88%, transparent);
    padding: 3px 8px;
    border: 1px solid color-mix(in srgb, var(--hp-warning) 35%, transparent);
    border-radius: var(--hp-radius-xs);
    white-space: nowrap;
    visibility: hidden;
}

.hp-map.is-measured .hp-map-chip {
    visibility: visible;
}

/* The key sits bottom-right, below every zone (comps 18/19), drawn with the real glyphs at
   legend scale; the top of the map belongs to the internet and region glyphs. */
.hp-map-legend {
    position: absolute;
    right: 18px;
    bottom: 10px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-legend);
    letter-spacing: 0.08em;
    color: var(--hp-text-disabled);
    text-align: right;
    line-height: 1.6;
}

.hp-map-legend-row {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 14px;
    white-space: nowrap;
}

.hp-map-legend-key {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}

.hp-map-legend-key .hp-glyph {
    margin: 0;
}

/* Reduced motion strips the glyph glows (hp-ui.css); the legend must not keep describing a
   signal that is no longer rendered — the meta-line state word carries "live" instead. */
@media (prefers-reduced-motion: reduce) {
    .hp-legend-glow {
        display: none;
    }

    .hp-map-lines {
        transition: none;
    }
}

/* ==========================================================================
   Systemkarta dashboard (comp 18): state line, registry table, SEK panel.
   Same discipline as the map block — no new literals.
   ========================================================================== */

.hp-state-line {
    margin: 0;
    font-size: var(--hp-sk-font-state-line);
    font-weight: 700;
}

.hp-state-line .hp-state-sep {
    color: var(--hp-text-disabled);
    font-weight: 400;
    margin: 0 6px;
}

.hp-state-ok { color: var(--hp-success); }
.hp-state-warn { color: var(--hp-warning); }
.hp-state-muted { color: var(--hp-text-muted); }
.hp-state-err { color: var(--hp-danger-light); }

.hp-dash-grid {
    display: grid;
    grid-template-columns: 1fr 316px;
    gap: 22px;
    align-items: start;
}

@media (max-width: 960px) {
    .hp-dash-grid {
        grid-template-columns: 1fr;
    }
}

.hp-registry-card {
    background: var(--hp-surface-raised);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    overflow: hidden;
}

.hp-registry-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
    padding: 12px 18px;
    border-bottom: 1px solid var(--hp-border-subtle);
}

.hp-registry-title {
    margin-right: auto;
}

/* Real text on the panel, unlike the map's aria-hidden labels: the muted step, which holds
   4.5:1 there; the disabled step measured 4.2:1 on the register card. */
.hp-registry-note {
    letter-spacing: 0.1em;
    color: var(--hp-text-muted);
}

/* Every HpSection heading speaks the same grammar as the register head (DESIGN.md: "Section
   headers: 10px mono letterspaced with the action in periwinkle on the right") — this is what
   makes Organization, Billing and the detail views read as one product. Hostport-scoped:
   Cupo keeps its own section voice. */
.hp-section-title {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-label);
    font-weight: 400;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

/* The head reused inside a detail-page section, where the card already draws the frame. */
.hp-registry-head--bare {
    border-bottom: none;
    padding-inline: 0;
}

.hp-registry-action {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    letter-spacing: inherit;
    color: var(--hp-primary-accent);
    cursor: pointer;
}

.hp-registry-action:hover {
    color: var(--hp-primary-light);
}

.hp-svc-row {
    display: flex;
    gap: 12px;
    align-items: baseline;
    width: 100%;
    padding: 10px 18px;
    border: none;
    border-bottom: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
    background: none;
    color: var(--hp-text);
    font-size: var(--hp-sk-font-row);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.hp-svc-row:last-child { border-bottom: none; }
.hp-svc-row:hover { background: var(--hp-surface-muted); }

.hp-svc-row[disabled] {
    cursor: default;
}

@media (max-width: 640px) {
    .hp-svc-row {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        grid-template-areas:
            "ty name state"
            "ty rel rel";
        row-gap: 0.15rem;
        align-items: baseline;
    }

    .hp-svc-ty { grid-area: ty; width: auto; padding-inline-end: 0.25rem; }
    .hp-svc-name { grid-area: name; width: auto; }
    .hp-svc-state { grid-area: state; }

    /* The relationship sentence gets its own line rather than "api-…". Two classes: the base
       .hp-svc-rel rule sits later in this sheet and would win a tie. */
    .hp-svc-row .hp-svc-rel {
        grid-area: rel;
        white-space: normal;
        overflow-wrap: anywhere;
    }
}

.hp-svc-ty {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-ty);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    width: 70px;
    flex-shrink: 0;
    color: var(--hp-text-muted);
}

.hp-svc-name {
    font-weight: 700;
    width: 128px;
    flex-shrink: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-svc-rel {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-svc-state {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-state);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    flex-shrink: 0;
}

.hp-sek-big {
    padding: 16px 18px 4px;
    font-weight: 800;
    font-size: var(--hp-sk-font-big);
    font-variant-numeric: tabular-nums;
}

.hp-sek-big small {
    font-size: var(--hp-font-xs);
    font-weight: 400;
    color: var(--hp-text-muted);
}

.hp-sek-kv {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 18px;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    border-top: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
}

.hp-sek-kv b {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-2xs);
    color: var(--hp-text);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-sek-hint {
    padding: 4px 18px 14px;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

/* The dashboard's one-row billing notice (BillingReadinessAlert Compact): same left rule and
   tint as the warning alert it stands in for, one line tall so the map stays in the viewport. */
.hp-readiness-strip {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.9rem;
    padding: 0.6rem 0.9rem;
    border: 1px solid color-mix(in srgb, var(--hp-warning) 35%, transparent);
    border-inline-start: 2px solid var(--hp-warning);
    border-radius: var(--hp-radius);
    background: var(--hp-alert-warning-bg);
    font-size: var(--hp-font-sm);
    color: var(--hp-text);
}

.hp-readiness-strip-icon {
    color: var(--hp-warning);
    flex-shrink: 0;
}

.hp-readiness-strip-text {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.75rem;
    flex: 1 1 18rem;
    min-width: 0;
}

.hp-readiness-strip-facts {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-readiness-strip-action {
    margin-inline-start: auto;
}

/* Comp 20: the deployment's log beside its details, under the rail. */
.hp-deploy-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 400px;
    gap: 1.5rem;
    align-items: start;
}

.hp-deploy-stage {
    min-width: 0;
}

.hp-deploy-details-body {
    padding: 14px 18px 16px;
}

.hp-deploy-details-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    padding: 12px 18px 16px;
    border-top: 1px solid var(--hp-border-subtle);
}

@media (max-width: 1180px) {
    .hp-deploy-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Comp 19: the service-detail focus view — map left, textual panel right. */

.hp-focus-grid {
    display: grid;
    grid-template-columns: 1fr 400px;
    gap: 22px;
    align-items: start;
}

@media (max-width: 960px) {
    .hp-focus-grid {
        grid-template-columns: 1fr;
    }
}

.hp-att-card {
    background: var(--hp-surface-raised);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
}

.hp-att-card + .hp-att-card {
    margin-top: 12px;
}

.hp-att-card-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
    font-weight: 700;
}

.hp-att-card-meta {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-state);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    flex-shrink: 0;
}

.hp-att-card-body {
    padding: 12px 16px;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
    display: grid;
    gap: 6px;
}

.hp-att-env {
    color: var(--hp-attachment-label);
}

/* A control inside the card body is UI, not data: it must not inherit the data face. */
.hp-att-card-body .rz-button,
.hp-att-card-body .rz-button .rz-button-text {
    font-family: var(--hp-brand-font);
    font-size: var(--hp-font-sm);
}

/* Comp 20: the deployment progress rail. Stop count comes from the plan, never hardcoded. */

.hp-deploy-rail {
    position: relative;
    /* RadzenStack aligns children start, not stretch — without this the rail shrink-wraps. */
    width: 100%;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    padding: 34px 28px 26px;
    overflow: hidden;
    background:
        radial-gradient(color-mix(in srgb, var(--hp-primary) 7%, transparent) 1px, transparent 1px),
        color-mix(in srgb, var(--hp-bg-deepest) 50%, transparent);
    background-size: 26px 26px, auto;
}

.hp-deploy-rail-stops {
    display: flex;
    align-items: flex-start;
}

.hp-deploy-rail-stop {
    flex: 1;
    position: relative;
    text-align: center;
    min-width: 0;
    padding-top: 22px;
}

.hp-deploy-rail-stop::before {
    content: "";
    position: absolute;
    top: 6px;
    right: 50%;
    width: 100%;
    height: 2px;
    background: color-mix(in srgb, var(--hp-primary-accent) 25%, transparent);
}

.hp-deploy-rail-stop:first-child::before {
    display: none;
}

.hp-deploy-rail-stop.is-done::before,
.hp-deploy-rail-stop.is-current::before {
    background: var(--hp-warning);
}

.hp-deploy-rail-dot {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 13px;
    height: 13px;
    border-radius: var(--hp-radius-round);
    z-index: 1;
}

.hp-deploy-rail-stop.is-done .hp-deploy-rail-dot {
    background: var(--hp-success);
    box-shadow: 0 0 12px color-mix(in srgb, var(--hp-success) 55%, transparent);
}

.hp-deploy-rail-stop.is-current .hp-deploy-rail-dot {
    background: var(--hp-warning);
    box-shadow: 0 0 14px color-mix(in srgb, var(--hp-warning) 65%, transparent);
}

.hp-deploy-rail-stop.is-todo .hp-deploy-rail-dot {
    background: transparent;
    border: 2px solid var(--hp-text-disabled);
}

.hp-deploy-rail-stop.is-failed .hp-deploy-rail-dot {
    background: var(--hp-danger);
    box-shadow: 0 0 12px color-mix(in srgb, var(--hp-danger) 55%, transparent);
}

.hp-deploy-rail-name {
    display: block;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-zone);
    color: var(--hp-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-deploy-rail-stop.is-todo .hp-deploy-rail-name {
    color: var(--hp-text-disabled);
}

.hp-deploy-rail-sub {
    display: block;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-zone-sub);
    color: var(--hp-text-disabled);
    margin-top: 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hp-deploy-rail-stop.is-current .hp-deploy-rail-sub {
    color: var(--hp-warning);
}

.hp-deploy-rail-stop.is-failed .hp-deploy-rail-sub {
    color: var(--hp-danger-light);
}

.hp-deploy-rail-dest {
    flex: 0 0 auto;
    padding-left: 26px;
}

.hp-deploy-rail-dest.is-pending .hp-glyph {
    border-style: dashed;
}

@media (prefers-reduced-motion: reduce) {
    .hp-deploy-rail-dot {
        box-shadow: none !important;
    }
}

/* The first-run map (Systemkarta empty state): a ghost sketch of a system behind the invitation. */

.hp-first-run {
    position: relative;
    width: 100%;
}

.hp-first-run-map {
    height: 380px;
}

.hp-first-run-map .hp-map-node {
    opacity: 0.5;
}

.hp-first-run-map .hp-map-node .hp-glyph,
.hp-first-run-map .hp-map-node .hp-glyph-cyl,
.hp-first-run-map .hp-map-node .hp-glyph-cyl::before {
    border-style: dashed;
    box-shadow: none;
}

/* The cloud and the globe are drawn strokes, not bordered boxes: a dashed border-style on
   them would conjure a medium box border out of nothing. The globe's rim dashes instead. */
.hp-first-run-map .hp-map-node .hp-glyph-kind-internet .hp-glyph,
.hp-first-run-map .hp-map-node .hp-glyph-kind-region .hp-glyph {
    border: 0;
}

.hp-first-run-map .hp-map-node .hp-globe-rim {
    stroke-dasharray: 2 2;
}

.hp-first-run-map .hp-map-chip {
    opacity: 0.6;
}

.hp-first-run-invite {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    text-align: center;
    /* The ghost sketch keeps the left third; the words keep the rest. */
    padding: 1.5rem 6% 1.5rem 38%;
}

@media (max-width: 900px) {
    .hp-first-run-invite {
        padding: 1.5rem;
    }

    .hp-first-run-map .hp-map-node,
    .hp-first-run-map .hp-map-chip {
        display: none;
    }
}

.hp-first-run-title {
    margin: 0;
    font-size: var(--hp-font-2xl);
    font-weight: 800;
}

.hp-first-run-text {
    margin: 0;
    color: var(--hp-text-muted);
    max-width: 46ch;
}

.hp-first-run-actions {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 0.5rem;
}

.hp-first-run-hint {
    margin: 0.4rem 0 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-legend);
    letter-spacing: 0.15em;
    color: var(--hp-text-disabled);
}

/* ---------------------------------------------------------------------------
   Scratch storage — the drop target and the object register.

   The drop target is one element, not a styled button beside a native control:
   the transparent <input type="file"> is stretched over the whole zone, so the
   browser's own file picking, drag-and-drop and keyboard activation keep working
   while the zone draws the design. Hence :focus-within for the ring — the thing
   that takes focus is invisible.
   --------------------------------------------------------------------------- */

.hp-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: 9.5rem;
    padding: 1.75rem 1.5rem;
    text-align: center;
    border: 1px dashed color-mix(in srgb, var(--hp-primary) 40%, transparent);
    border-radius: var(--hp-radius-lg);
    background:
        radial-gradient(115% 130% at 50% 0%,
            color-mix(in srgb, var(--hp-primary) 9%, transparent), transparent 72%),
        var(--hp-bg-base);
    transition: border-color 160ms ease, background-color 160ms ease;
}

.hp-drop-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.hp-drop:hover,
.hp-drop:focus-within {
    border-color: var(--hp-primary-accent);
}

.hp-drop:focus-within {
    box-shadow: var(--hp-focus-ring);
}

/* Dragging over: the whole zone answers, because the pointer is nowhere near a button. */
.hp-drop--over {
    border-color: var(--hp-primary-accent);
    border-style: solid;
    background-color: var(--hp-surface-hover);
}

.hp-drop--busy,
.hp-drop--busy .hp-drop-input {
    cursor: default;
}

.hp-drop-icon {
    font-size: var(--hp-font-4xl);
    line-height: 1;
    color: var(--hp-primary-accent);
}

.hp-drop-title {
    margin: 0;
    font-weight: 700;
    color: var(--hp-text);
}

.hp-drop-hint {
    margin: 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
}

/* The picked file, shown inside the same zone: the file <input> must never unmount — the
   presigned PUT reads the bytes back out of it (app.js putFileFromInput), and a retry after a
   failed upload has no other source for them. So the zone swaps its own contents instead. */
.hp-drop-file {
    font-family: var(--hp-font-mono);
    overflow-wrap: anywhere;
}

.hp-upload-fields {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 0.75rem;
    align-items: end;
}

@media (max-width: 720px) {
    .hp-upload-fields {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* One object per row in the register grammar (.hp-svc-row): mono key, a mono sentence of
   facts, the countdown that is this product's whole point, then the state word. */
.hp-obj-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    column-gap: 1.25rem;
    row-gap: 0.35rem;
    padding: 0.7rem 1.125rem;
    border-bottom: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
}

.hp-obj-row:last-child {
    border-bottom: none;
}

.hp-obj-row:hover {
    background: var(--hp-surface-muted);
}

.hp-obj-main {
    min-width: 0;
}

.hp-obj-key {
    margin: 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-row);
    font-weight: 700;
    color: var(--hp-text);
    overflow-wrap: anywhere;
}

.hp-obj-meta {
    margin: 0.15rem 0 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Each row is its own grid, so nothing aligns the countdowns down the register unless this
   column is given a width — a row carrying a "Retry upload" button dragged its own countdown
   inwards and the column read as ragged. */
.hp-obj-life {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.15rem;
    min-width: 10rem;
    text-align: right;
    font-family: var(--hp-font-mono);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.hp-obj-left {
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-secondary);
}

.hp-obj-left--soon {
    color: var(--hp-warning);
}

.hp-obj-state {
    font-size: var(--hp-sk-font-state);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-obj-state--live { color: var(--hp-success); }
.hp-obj-state--pending { color: var(--hp-warning); }
.hp-obj-state--gone { color: var(--hp-danger); }

.hp-obj-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    justify-self: end;
}

/* One column narrow: keeping the actions beside the key squeezed the fact sentence to about
   fourteen characters, and a content type broke across four lines. */
@media (max-width: 720px) {
    .hp-obj-row {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 0.5rem;
    }

    .hp-obj-life {
        align-items: flex-start;
        min-width: 0;
        text-align: left;
    }

    .hp-obj-actions {
        justify-self: start;
    }
}

/* The register's own footer strip (load more, counts) — flush with the rows above it. */
.hp-obj-foot {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 1.125rem;
    border-top: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
}

/* Empty register: the upload zone right above already carries the cloud and the invitation,
   so this half states the other way in — and shows it. */
.hp-obj-blank {
    padding: 1.75rem 1.125rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.hp-obj-blank-title {
    margin: 0;
    font-size: var(--hp-font-md);
    font-weight: 700;
    color: var(--hp-text);
}

.hp-obj-blank-text {
    margin: 0;
    max-width: 62ch;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-sm);
}

/* ---- Code editor (HpCodeEditor: CodeMirror 6, styled inside the bundle from these tokens) ---- */

.hp-code-editor {
    width: 100%;
    min-width: 0;
}

.hp-code-editor .cm-editor {
    height: var(--hp-code-editor-height);
}

.hp-code-editor .cm-scroller {
    overflow: auto;
}

/* ---- Function page: Code view (editor, try-it pane, revision rows) ---- */

.hp-fn-editor-head {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.hp-fn-editor-title {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.hp-fn-editor-state {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-fn-editor-state--dirty {
    color: var(--hp-warning);
}

.hp-fn-invoke-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: 1.25rem;
    align-items: start;
}

@media (max-width: 900px) {
    .hp-fn-invoke-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.hp-fn-invoke-input,
.hp-fn-invoke-output {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 0;
}

.hp-fn-invoke-output .hp-code-block {
    margin: 0;
    max-height: 22rem;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.hp-fn-invoke-empty {
    color: var(--hp-text-disabled);
    font-style: italic;
}

.hp-fn-invoke-meta {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-transform: none;
    letter-spacing: normal;
    color: var(--hp-text-muted);
}

.hp-fn-revisions {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    overflow: hidden;
}

.hp-fn-revision {
    display: grid;
    grid-template-columns: 8.5rem minmax(0, 1fr) auto;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 1rem;
    background: var(--hp-surface-raised);
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-fn-revision:first-child {
    border-top: none;
}

.hp-fn-revision--active {
    box-shadow: inset 3px 0 0 var(--hp-success);
}

.hp-fn-revision-hash {
    font-family: var(--hp-font-mono);
    color: var(--hp-text);
}

.hp-fn-revision-meta {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
    overflow-wrap: anywhere;
}

.hp-fn-revision-actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
}

@media (max-width: 700px) {
    .hp-fn-revision {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .hp-fn-revision-meta {
        grid-column: 1 / -1;
    }
}

/* Functions and Jobs read in the shared detail grammar above (frame, view rail, section head,
   card and panel); what follows is layout safety plus the components only these pages have. */
.hp-functions,
.hp-jobs {
    min-width: 0;
}

.hp-functions .hp-card-body-flush {
    overflow-x: auto;
}

.hp-functions .rz-form-field,
.hp-jobs .rz-form-field {
    min-width: 0;
    width: 100%;
}

.hp-functions .rz-data-grid,
.hp-functions .hp-code-block,
.hp-jobs .hp-code-snippet {
    max-width: 100%;
}

.hp-functions .hp-code-block,
.hp-jobs .hp-code-snippet {
    overflow: auto;
}

.hp-jobs .hp-code-snippet {
    max-height: 24rem;
}

.hp-jobs .rz-column,
.hp-jobs .rz-stack {
    min-width: 0;
}

.hp-functions .hp-att-card-body,
.hp-jobs code,
.hp-jobs .rz-text-body2,
.hp-jobs .rz-text-caption {
    overflow-wrap: anywhere;
}

.hp-functions .hp-att-card-head {
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* "Node.js 22" wraps inside its stat box instead of truncating to "Node.js…". */
.hp-functions .hp-stat-card-value {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
}

.hp-fn-trigger-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.5rem;
}

.hp-fn-trigger-grid .hp-section {
    display: flex;
    flex-direction: column;
}

.hp-fn-trigger-grid .hp-section-content {
    flex: 1;
}

.hp-fn-trigger-grid .hp-card {
    height: 100%;
}

.hp-fn-help {
    margin: 0;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
    line-height: 1.6;
}

.hp-fn-access {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.hp-fn-access-options {
    border: 0;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
    min-width: 0;
}

.hp-fn-access-options legend {
    padding: 0;
    margin-bottom: 0.75rem;
    font-size: var(--hp-font-sm);
    font-weight: 600;
}

.hp-fn-access-option {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 1rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
    cursor: pointer;
    background: var(--hp-bg-base);
}

.hp-fn-access-option.is-selected {
    border-color: var(--hp-primary);
    background: var(--hp-primary-muted);
}

.hp-fn-access-option input {
    margin-top: 0.25rem;
    accent-color: var(--hp-primary);
    flex-shrink: 0;
}

.hp-fn-access-option strong {
    display: block;
    font-size: var(--hp-font-sm);
}

.hp-fn-access-option small {
    display: block;
    margin-top: 0.4rem;
    color: var(--hp-text-muted);
    line-height: 1.5;
    font-size: var(--hp-font-xs);
}

.hp-fn-access-option:focus-within {
    outline: 2px solid var(--hp-primary);
    outline-offset: 3px;
}

.hp-fn-access-options:disabled .hp-fn-access-option {
    cursor: default;
    opacity: 0.65;
}

.hp-fn-access-save {
    display: flex;
    gap: 1rem;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
}

.hp-fn-access-save p,
.hp-fn-endpoint p {
    margin: 0;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-sm);
    line-height: 1.6;
}

.hp-fn-access-save p {
    flex: 1 1 15rem;
}

.hp-fn-endpoint {
    padding-top: 1.25rem;
    border-top: 1px solid var(--hp-border-subtle);
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    min-width: 0;
}

.hp-fn-endpoint-url {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    flex-wrap: wrap;
    padding: 0.875rem;
    background: var(--hp-bg-base);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
}

.hp-fn-endpoint-url code {
    flex: 1 1 15rem;
    overflow-wrap: anywhere;
    font-size: var(--hp-font-xs);
}

.hp-fn-open {
    color: var(--hp-primary-accent);
    font-size: var(--hp-font-sm);
}

.hp-fn-trigger-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-fn-advanced {
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
}

.hp-fn-advanced summary {
    cursor: pointer;
    padding: 1.25rem;
    font-weight: 600;
}

.hp-fn-advanced summary span {
    display: inline-block;
    margin-left: 0.75rem;
    color: var(--hp-text-muted);
    font-weight: 400;
    font-size: var(--hp-font-xs);
}

.hp-fn-advanced-body {
    padding: 0 1.25rem 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.hp-fn-invocations .hp-card-body {
    padding: 1rem 1.25rem;
}

.hp-fn-create .rz-selectbar {
    display: flex;
    flex-wrap: wrap;
}

.hp-fn-create .rz-selectbar > div {
    flex: 1;
}

.hp-fn-create .rz-form-field {
    width: 100%;
}

/* Three access cards need the full-width stage; beside the panel they stack. */
@media (max-width: 1400px) {
    .hp-fn-access-options {
        grid-template-columns: 1fr;
    }

    .hp-fn-access-option {
        padding: 0.875rem;
    }

    .hp-fn-access-option small {
        margin-top: 0.2rem;
    }
}

@media (max-width: 1180px) {
    .hp-fn-access-options {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 700px) {
    .hp-fn-trigger-grid,
    .hp-fn-access-options {
        grid-template-columns: 1fr;
    }
}

.hp-jobs-toolbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.hp-jobs-help {
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
    line-height: 1.6;
}

.hp-jobs-filter {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.hp-jobs-filter > span {
    display: block;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-jobs-filter select {
    width: 100%;
    min-height: 44px;
    padding: 0.625rem 0.875rem;
    background: var(--hp-bg-deepest);
    color: var(--hp-text);
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    font: inherit;
}

.hp-jobs-notice {
    display: flex;
    gap: 1.25rem;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    padding: 1.25rem;
    border: 1px solid var(--hp-border-subtle);
    border-left: 3px solid var(--hp-primary);
    background: var(--hp-primary-muted);
    border-radius: var(--hp-radius-lg);
}

.hp-jobs-notice > div {
    flex: 1 1 16rem;
}

.hp-jobs-notice p {
    margin: 0.375rem 0 0;
    font-size: var(--hp-font-sm);
    line-height: 1.6;
    color: var(--hp-text-muted);
}

.hp-jobs-schedule-form-title {
    margin: 0;
    font-size: var(--hp-font-lg);
    font-weight: 600;
}

.hp-jobs-disclosure {
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
}

.hp-jobs-disclosure > summary {
    cursor: pointer;
    padding: 1.25rem;
    font-weight: 600;
}

.hp-jobs-disclosure > summary span {
    font-weight: 400;
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
    margin-left: 0.5rem;
}

.hp-jobs-disclosure-body {
    padding: 0 1.25rem 1.25rem;
}

.hp-jobs-payload {
    width: 100%;
    min-width: 0;
}

.hp-jobs-payload summary {
    cursor: pointer;
    font-size: var(--hp-font-xs);
    color: var(--hp-primary-accent);
    padding: 0.5rem 0;
}

.hp-jobs-error {
    color: var(--hp-danger);
    font-size: var(--hp-font-sm);
    margin: 0;
    line-height: 1.6;
    overflow-wrap: anywhere;
}

.hp-jobs-receipt {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: var(--hp-font-xs);
    min-width: 0;
}

.hp-jobs-receipt span {
    color: var(--hp-text-muted);
}

.hp-jobs-schedule .hp-card-body > .rz-stack > .rz-stack:first-child {
    flex: 1 1 16rem;
}

.hp-jobs-schedule-form {
    border-top: 1px solid var(--hp-border-subtle);
    padding-top: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.hp-jobs-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.25rem;
}

.hp-jobs-save {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    background: var(--hp-bg-deepest);
    padding: 1.25rem;
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius-lg);
}

.hp-jobs-save strong {
    font-size: var(--hp-font-sm);
}

.hp-jobs .hp-jobs-processing-choices {
    grid-template-columns: minmax(0, 1fr);
}

.hp-jobs-setup > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
    font-size: var(--hp-font-sm);
    padding-bottom: 0.75rem;
}

@media (max-width: 700px) {
    .hp-jobs-form-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .hp-jobs-save .hp-jobs-toolbar {
        width: 100%;
    }

    .hp-jobs .hp-processing-status {
        flex-wrap: wrap;
    }

    .hp-jobs .hp-processing-status-action {
        margin-left: 0;
    }

    .hp-jobs .hp-snippet-head {
        flex-wrap: wrap;
        gap: 0.5rem;
    }
}

/* Registry links retain the same row grammar as non-navigable entries. */
a.hp-svc-row {
    text-decoration: none;
    color: var(--hp-text);
}

a.hp-svc-row:focus-visible {
    outline: 2px solid var(--hp-primary-accent);
    outline-offset: -3px;
}

.hp-svc-row--static {
    cursor: default;
}

.hp-registry-card .hp-registry-action {
    min-height: 2.75rem;
    display: inline-flex;
    align-items: center;
}

.hp-registry-card .hp-svc-row {
    min-height: 3rem;
}

.hp-registry-card .hp-svc-name {
    width: clamp(8rem, 25%, 20rem);
}

@media (max-width: 640px) {
    .hp-registry-card .hp-svc-row {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "ty state" "name name" "rel rel";
        gap: .375rem .75rem;
    }

    .hp-registry-card .hp-svc-name {
        width: auto;
        white-space: normal;
        overflow-wrap: anywhere;
    }

    .hp-registry-card .hp-svc-state {
        overflow-wrap: anywhere;
        min-width: 0;
    }
}

/* ── Visitor analytics (web-app Traffic and Configuration views) ─────────────────────────── */
.hp-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.hp-analytics-card-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--hp-space-3);
    margin-bottom: var(--hp-space-2);
}

.hp-analytics-quality {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--hp-space-2);
    font-size: var(--hp-font-2xs);
}

.hp-analytics-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--hp-font-xs);
}

.hp-analytics-table th,
.hp-analytics-table td {
    text-align: left;
    padding: var(--hp-space-1) var(--hp-space-2);
    border-bottom: 1px solid var(--hp-border-subtle);
    vertical-align: top;
}

.hp-analytics-table th {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-2xs);
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
}

.hp-analytics-table .hp-analytics-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.hp-analytics-details {
    margin-top: var(--hp-space-2);
    max-height: 24rem;
    overflow: auto;
}

.hp-analytics-details > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
    font-size: var(--hp-font-xs);
}

.hp-analytics-details > summary:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-analytics-gap-list {
    margin: var(--hp-space-2) 0 0;
    padding-left: var(--hp-space-4);
    color: var(--hp-text-muted);
    font-size: var(--hp-font-xs);
}

.hp-analytics-rule-row {
    display: grid;
    grid-template-columns: minmax(6rem, 1fr) minmax(10rem, 2fr) minmax(8rem, 1.5fr) auto;
    gap: var(--hp-space-2);
    align-items: center;
}

@media (max-width: 640px) {
    .hp-analytics-rule-row {
        grid-template-columns: 1fr;
    }
}

.hp-analytics-error {
    color: var(--hp-danger);
}

.hp-analytics-snippet {
    display: flex;
    align-items: flex-start;
    gap: var(--hp-space-2);
}

.hp-analytics-snippet .hp-code-snippet {
    flex: 1;
    min-width: 0;
    white-space: pre-wrap;
    word-break: break-all;
}

/* Navigation flow: the map's line vocabulary on a dot-grid well. The drawing keeps its 640 px
   width and pans on a phone, like the system map; the table under it stays full width. Nothing
   here animates, so reduced motion changes nothing. */
.hp-analytics-flow-caption {
    display: block;
    margin: 0 0 var(--hp-space-2);
}

.hp-flow-frame {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

@media (max-width: 640px) {
    .hp-flow-frame {
        mask-image: linear-gradient(to right, black calc(100% - 36px), transparent);
    }

    .hp-flow-frame > .hp-flow-well {
        min-width: 640px;
    }
}

.hp-flow-well {
    aspect-ratio: 640 / 400;
}

.hp-flow {
    display: block;
    width: 100%;
    height: 100%;
}

/* stroke-width is per edge (a presentation attribute set from the count), so the rule must not
   set one; the map's line class would override it. */
.hp-flow-link {
    fill: none;
    stroke: color-mix(in srgb, var(--hp-primary-accent) 55%, transparent);
    stroke-linecap: round;
}

.hp-flow-link--loop {
    stroke: color-mix(in srgb, var(--hp-primary) 60%, transparent);
}

.hp-flow-node circle {
    fill: var(--hp-surface-raised);
    stroke: var(--hp-primary-accent);
    stroke-width: 1.4;
}

.hp-flow-node-label {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-map-font-chip);
    fill: var(--hp-text);
}

/* Radzen renders a caption as an inline span, so two notes in a row would run into one sentence;
   each note is its own line. */
.hp-analytics-note {
    display: block;
    margin: var(--hp-space-2) 0 0;
}

/* Serving markers keep the deploy grammar's amber. The list is the chart's accessible twin for
   markers: a deployment is never named only inside the SVG. */
.hp-analytics-marker-list {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--hp-space-1) var(--hp-space-4);
    margin: var(--hp-space-2) 0 0;
    padding: 0;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-analytics-marker-list .hp-mono {
    color: var(--hp-text);
}

.hp-analytics-marker-glyph {
    color: var(--hp-warning);
}

/* ===== Plan gate, compact (HpPlanUpsell Compact="true"): the gate lives inside the section it
   gates, one line, the upgrade beside it. ===== */
.hp-plan-gate {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.6rem 0.85rem;
    border-radius: var(--hp-radius);
    border: 1px dashed var(--hp-border);
    background: color-mix(in srgb, var(--hp-primary) 6%, transparent);
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
}

.hp-plan-gate-icon {
    font-size: var(--hp-font-md);
    color: var(--hp-primary-accent);
}

.hp-plan-gate-text {
    flex: 1 1 18rem;
    min-width: 0;
}

.hp-plan-gate-text strong {
    color: var(--hp-text);
    font-weight: 600;
}

/* ===== Traffic view (VisitorAnalyticsPanel, 2026-09-17): one clock, one story. ===== */
.hp-traffic {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.hp-traffic-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
    flex-wrap: wrap;
}

.hp-traffic-head-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* In-page choice chips (period, series). The old route-chip class lived with the retired request
   analyzer; these are the same shape under a name that says what they are. */
.hp-view-chips {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.hp-view-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.75rem;
    border-radius: var(--hp-radius-pill);
    border: 1px solid var(--hp-border);
    background: var(--hp-surface-raised);
    color: var(--hp-text);
    font-size: var(--hp-font-xs);
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.hp-view-chip:hover:not(:disabled) {
    border-color: var(--hp-primary);
}

.hp-view-chip:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-view-chip:disabled {
    cursor: not-allowed;
    color: var(--hp-text-muted);
    border-style: dashed;
}

.hp-view-chip--active {
    border-color: var(--hp-primary);
    background: var(--hp-primary-muted);
    color: var(--hp-primary-accent);
}

.hp-traffic-note {
    margin: 0;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

/* The chart head holds the series chips on the left and the quality line on the right; both wrap
   under each other on a phone. */
.hp-traffic-chart-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.hp-traffic-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
    align-items: start;
}

.hp-traffic-grid > .hp-card {
    height: 100%;
}

@media (max-width: 900px) {
    .hp-traffic-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.hp-traffic-card-unit {
    display: block;
    margin: -0.25rem 0 0.5rem;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-traffic-card-figure {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-font-xs);
    color: var(--hp-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* "About these numbers": every caveat the cards used to repeat, once, closed by default. */
.hp-traffic-about {
    border: 1px solid var(--hp-border-subtle);
    border-radius: var(--hp-radius);
    padding: 0.6rem 0.9rem;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

.hp-traffic-about > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
    font-weight: 600;
}

.hp-traffic-about > summary:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-traffic-about ul {
    margin: 0.5rem 0 0;
    padding-left: 1.25rem;
}

.hp-traffic-about li + li {
    margin-top: 0.25rem;
}

/* A compact "turn it on" card: the view keeps its shape instead of a headline empty state. */
.hp-traffic-setup {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.hp-traffic-setup-text {
    flex: 1 1 20rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.hp-traffic-setup-title {
    font-weight: 600;
    color: var(--hp-text);
}

/* Settings drawer: the workflow drawer's frame, with a segmented switch between its parts. */
.hp-settings-drawer {
    width: min(640px, 100vw);
}

.hp-settings-drawer .hp-section {
    margin-bottom: 0;
}

.hp-drawer-tabs {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--hp-border-subtle);
    margin-bottom: 0.25rem;
}

.hp-drawer-tab {
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 0.5rem 0.75rem;
    font: inherit;
    font-size: var(--hp-font-xs);
    font-weight: 600;
    color: var(--hp-text-muted);
    cursor: pointer;
}

.hp-drawer-tab:hover {
    color: var(--hp-text);
}

.hp-drawer-tab:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-drawer-tab--active {
    color: var(--hp-text);
    border-bottom-color: var(--hp-primary);
}

.hp-drawer-body {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* ===== App detail, Access view (AppAccessView): the public switch with its state line, the
   hostnames register (one table in a flush card, platform row first) and allowed-caller rows.
   Type sizes come from the register tokens; nothing here goes below the 10px floor. ===== */
.hp-access-switch {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}

.hp-access-switch-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.hp-access-switch-label {
    font-weight: 600;
    color: var(--hp-text);
}

.hp-access-switch-state,
.hp-access-note {
    margin: 0;
    font-size: var(--hp-font-xs);
    color: var(--hp-text-muted);
}

/* A hostname never wraps: on a phone the table grows past the card and pans inside this
   container, the way the map does, instead of breaking "testsite-567f39d2" five letters a line. */
.hp-hostnames-scroll {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

/* The same fade the flow drawing uses: a phone sees that the table continues to the right. */
@media (max-width: 640px) {
    .hp-hostnames-scroll {
        mask-image: linear-gradient(to right, black calc(100% - 36px), transparent);
    }
}

.hp-hostnames-table {
    min-width: 100%;
}

.hp-hostname-cell code {
    white-space: nowrap;
}

/* The analytics table grammar is reused for its head row; the cells are looser because each row
   carries a copy button and two actions, and the outer padding lines the hostname up with the
   add row under the table. */
.hp-hostnames-table th,
.hp-hostnames-table td {
    padding: var(--hp-space-2) var(--hp-space-3);
    vertical-align: middle;
}

.hp-hostnames-table th:first-child,
.hp-hostnames-table td:first-child {
    padding-inline-start: 1.5rem;
}

.hp-hostnames-table th:last-child,
.hp-hostnames-table td:last-child {
    padding-inline-end: 1.5rem;
}

.hp-hostnames-table tbody tr:last-child td {
    border-bottom: none;
}

.hp-hostname-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: var(--hp-sk-font-row);
}

.hp-hostname-type {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-ty);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
    white-space: nowrap;
}

.hp-hostname-state {
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-state);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
}

.hp-hostname-actions {
    text-align: right;
    white-space: nowrap;
}

.hp-hostname-actions .rz-button + .rz-button {
    margin-inline-start: 0.35rem;
}

.hp-hostname-note,
.hp-hostname-dns {
    margin: 0.35rem 0 0;
    font-size: var(--hp-font-2xs);
    color: var(--hp-text-muted);
}

.hp-hostname-dns > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
}

.hp-hostname-dns > summary:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-hostname-dns-note {
    margin: 0.35rem 0 0;
}

.hp-hostname-dns-records {
    display: grid;
    gap: 0.25rem;
    margin-top: 0.35rem;
}

.hp-hostname-dns-record {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    font-size: var(--hp-sk-font-data);
}

.hp-hostname-dns-record code {
    color: var(--hp-text);
    overflow-wrap: anywhere;
}

.hp-hostname-add,
.hp-caller-attach {
    display: flex;
    align-items: flex-end;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.hp-hostname-add {
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--hp-border-subtle);
}

.hp-hostname-add .rz-form-field,
.hp-caller-attach .rz-form-field {
    flex: 1 1 16rem;
    min-width: 0;
    max-width: 28rem;
}

/* A caller row is one line: the head is the whole card, so its divider has nothing to divide. */
.hp-caller-card .hp-att-card-head {
    align-items: center;
    border-bottom: none;
}

.hp-caller-id {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
    min-width: 0;
}

/* ===== Disclosure (<details>) for secondary detail inside a card: the analytics-details voice
   (summary in periwinkle, xs type) under a neutral name so panels outside analytics can share
   it. The body is a plain stack — the card already draws the frame. ===== */
.hp-disclosure > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
    font-size: var(--hp-font-xs);
}

.hp-disclosure > summary:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-disclosure-body {
    display: grid;
    gap: var(--hp-space-3);
    padding-top: var(--hp-space-3);
}

/* ===== APPUI-5 — web app Environment view: the variable register and attachment card actions ===== */

/* The register grammar (.hp-svc-row) with its own cells — key, value, source sentence, actions —
   under its own class: .hp-svc-row's phone layout is a named-area grid for TYPE/name/relationship/
   state and would auto-place these cells into the wrong slots. */
.hp-env-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.hp-env-row {
    display: grid;
    grid-template-columns: minmax(8rem, 0.9fr) minmax(0, 1.4fr) minmax(0, 1fr) auto;
    grid-template-areas: "key value src actions";
    align-items: center;
    column-gap: 1rem;
    row-gap: 0.25rem;
    min-height: 3rem;
    padding: 10px 18px;
    border-bottom: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
    font-size: var(--hp-sk-font-row);
}

.hp-env-row:last-child {
    border-bottom: none;
}

.hp-env-row:hover {
    background: var(--hp-surface-muted);
}

.hp-env-key {
    grid-area: key;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    min-width: 0;
    font-family: var(--hp-font-mono);
    font-weight: 700;
    color: var(--hp-text);
    overflow-wrap: anywhere;
}

/* Values wrap rather than ellipsize: a truncated connection string is a false statement. */
.hp-env-value {
    grid-area: value;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    min-width: 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text);
    overflow-wrap: anywhere;
}

.hp-env-next {
    color: var(--hp-warning);
}

.hp-env-src {
    grid-area: src;
    min-width: 0;
    font-family: var(--hp-font-mono);
    font-size: var(--hp-sk-font-data);
    color: var(--hp-text-muted);
    overflow-wrap: anywhere;
}

.hp-env-actions {
    grid-area: actions;
    display: flex;
    justify-content: flex-end;
    gap: 0.25rem;
}

/* A badge is UI inside a mono cell: it keeps the badge face, not the register's data face. */
.hp-env-row .hp-badge {
    font-family: var(--hp-brand-font);
}

@media (max-width: 640px) {
    .hp-env-row {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "key actions"
            "value value"
            "src src";
    }
}

/* Attachment cards on the Environment view: the resource name is the link to its page and keeps
   the card's text colour, like a.hp-svc-row; the small action row sits under the two fact lines. */
.hp-att-card-name {
    color: var(--hp-text);
    text-decoration: none;
    border-radius: var(--hp-radius-xs);
}

.hp-att-card-name:hover {
    color: var(--hp-primary-accent);
    text-decoration: underline;
}

.hp-att-card-name:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-att-card-body code {
    font: inherit;
}

.hp-att-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.25rem;
}

.hp-att-routes {
    display: grid;
    gap: 0.4rem;
    margin-top: 0.5rem;
    padding-top: 0.6rem;
    border-top: 1px solid color-mix(in srgb, var(--hp-primary) 9%, transparent);
}

.hp-att-route,
.hp-att-route-add {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.hp-att-route code {
    color: var(--hp-text);
}

/* Route controls are UI, not data: brand face at the small size, like .hp-att-card-body .rz-button. */
.hp-att-route-add .rz-label,
.hp-att-route .hp-badge,
.hp-att-routes-help {
    font-family: var(--hp-brand-font);
    font-size: var(--hp-font-xs);
}

.hp-att-routes-help {
    color: var(--hp-text-secondary);
}

.hp-att-routes-help p {
    margin: 0;
}

.hp-att-disclosure {
    margin-top: 0.35rem;
}

.hp-att-disclosure > summary {
    cursor: pointer;
    color: var(--hp-primary-accent);
}

.hp-att-disclosure > summary:focus-visible {
    outline: none;
    box-shadow: var(--hp-focus-ring);
}

.hp-att-disclosure p {
    margin-top: 0.35rem;
    color: var(--hp-text-muted);
}
