/* ─────────────────────────────────────────────────────────────────────────
 * Digital Cloud — VPS Constructor widget
 * Faithful port of the 18.05.2026 reference (Constructor 18.05.2026.html).
 * All rules scoped under .dc-constructor to avoid leaking into other themes.
 * ──────────────────────────────────────────────────────────────────────── */

.dc-constructor {
    /* digitalcloud's global style.css turns every <section> into a flex
     * container with `justify-content: center` — that makes our `.dc-c__inner`
     * shrink to content width inside the flex (no `flex: 1` on it), which
     * collapsed the whole card. Force the standard block layout instead. */
    display: block;

    /* Horizontal spacing comes from `.dc-c__inner`'s `padding-inline: 40px`
     * (matches the site-wide `.container` rule). Vertical padding is part of
     * the landing-page "50px between blocks" rhythm (25px top + 25px bottom
     * on every major section — see `.tariffs`, `.default-block`, etc.). */
    padding-block: 25px;
    padding-inline: 0;

    /* Palette — matches the reference, kept local so other themes don't inherit. */
    --dc-bg: #f4f5f7;
    --dc-card: #ffffff;
    --dc-ink: #0b1220;
    --dc-ink-2: #1a2236;
    --dc-muted: #7a869a;
    --dc-muted-2: #9aa3b6;
    --dc-line: #e6eaf0;
    --dc-line-2: #eef1f6;

    --dc-blue: #1d8cf0;
    --dc-blue-deep: #0a4fd4;
    --dc-blue-soft: #e8f2fd;
    --dc-blue-soft-2: #f3f8fe;
    --dc-blue-ink: #0d3a8c;

    --dc-green: #19b893;
    --dc-orange: #ff7a3d;
    --dc-red: #ef4f5e;

    --dc-shadow-md: 0 8px 24px rgba(15, 42, 90, .06), 0 2px 6px rgba(15, 42, 90, .04);

    color: var(--dc-ink);
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    -webkit-font-smoothing: antialiased;
}

.dc-constructor *,
.dc-constructor *::before,
.dc-constructor *::after {
    box-sizing: border-box;
}

/* :where() drops the specificity of this baseline button reset to (0,0,0)
 * so every component button class below (.dc-c__loc-btn, .dc-c__pill, etc.)
 * wins automatically when it declares its own border / background. */
:where(.dc-constructor button) {
    font-family: inherit;
    cursor: pointer;
    background: none;
    border: none;
}

.dc-c__inner {
    /* Match the page-wide `.container` rule from style.css verbatim
     * (max-width 1140 + 40px horizontal padding + box-sizing border-box)
     * so the visible card aligns with the featured tariffs row and the
     * Check Speed block above and below — effective content width = 1060px. */
    max-width: 1140px;
    width: 100%;
    margin: 0 auto;
    padding-inline: 40px;
    box-sizing: border-box;
}

.dc-c__grid {
    background: var(--dc-card);
    border: 1px solid var(--dc-line);
    border-radius: 22px;
    box-shadow: var(--dc-shadow-md);
    /* `overflow: clip` keeps the rounded-corner clipping behaviour of the
     * old `overflow: hidden` (children stay inside the radius) while still
     * letting `overflow-clip-margin` carve out room for the disabled-tile
     * hover popup that extends below its tile. The 120px margin covers a
     * worst-case card height + arrow + gap for tiles in the very last row
     * of the software / version grids. */
    overflow: clip;
    overflow-clip-margin: 120px;
    display: grid;
    /* `minmax(0, 1fr)` lets the left column shrink below its min-content
     * (city names like "St. Petersburg" force long min-widths via `white-space:
     * nowrap` on .dc-c__city). Without this, the left column blows past `1fr`,
     * pushing the right sidebar partially behind the card's `overflow: hidden`. */
    grid-template-columns: minmax(0, 1fr) 340px;
}

/* ───────────────────────── LEFT COLUMN ──────────────────────────── */

.dc-c__left {
    padding: 28px;
    display: flex;
    flex-direction: column;
    gap: 26px;
    /* Belt-and-braces: grid items default to `min-width: min-content`, which
     * makes long unbreakable strings (e.g. city names in the location grid)
     * force the column wider. `min-width: 0` opts out and lets children
     * truncate / wrap inside the assigned column width. */
    min-width: 0;
}

.dc-c__section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 14px;
}

.dc-c__section-title {
    font-size: 14px;
    font-weight: 800;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--dc-blue-ink);
}

.dc-c__section-hint {
    font-size: 11px;
    color: var(--dc-muted);
    font-weight: 500;
}

/* ── Sliders ───────────────────────────────────────────────────── */

.dc-c__slider-stack {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.dc-c__slider-row {
    display: grid;
    grid-template-columns: 36px 1fr 110px;
    align-items: center;
    gap: 14px;
}

.dc-c__s-icon {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--dc-blue-soft);
    color: var(--dc-blue);
}

.dc-c__s-icon--ram {
    background: rgba(25, 184, 147, .10);
    color: var(--dc-green);
}

.dc-c__s-icon--disk {
    background: rgba(255, 122, 61, .10);
    color: var(--dc-orange);
}

.dc-c__s-icon svg {
    width: 18px;
    height: 18px;
}

.dc-c__s-val {
    font-size: 15px;
    font-weight: 800;
    color: var(--dc-ink);
    text-align: right;
    white-space: nowrap;
    letter-spacing: -.01em;
    font-variant-numeric: tabular-nums;
}

.dc-c__s-val span {
    font-size: 11px;
    font-weight: 600;
    color: var(--dc-muted);
    margin-left: 3px;
}

.dc-c__range-wrap {
    position: relative;
    height: 24px;
    display: flex;
    align-items: center;
}

/* Selector specificity bumped to `.dc-constructor input.dc-c__range` (0,3,1) so it
 * beats the theme-wide `input:not([type="checkbox"])` rule in style.css that adds
 * a 1px border + 20px padding to every input on the site. */
.dc-constructor input.dc-c__range {
    -webkit-appearance: none;
    appearance: none;
    position: absolute;
    width: 100%;
    height: 24px;
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
    margin: 0;
    font-size: inherit;
    outline: none;
    z-index: 2;
    cursor: pointer;
}

.dc-c__range::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    border: 3px solid var(--dc-blue);
    box-shadow: 0 4px 10px rgba(29, 140, 240, .28);
    transition: transform .14s, box-shadow .14s;
}

.dc-c__range::-moz-range-thumb {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    border: 3px solid var(--dc-blue);
    box-shadow: 0 4px 10px rgba(29, 140, 240, .28);
}

.dc-c__range:hover::-webkit-slider-thumb {
    transform: scale(1.12);
}

.dc-c__range--ram::-webkit-slider-thumb {
    border-color: var(--dc-green);
    box-shadow: 0 4px 10px rgba(25, 184, 147, .28);
}

.dc-c__range--ram::-moz-range-thumb {
    border-color: var(--dc-green);
}

.dc-c__range--disk::-webkit-slider-thumb {
    border-color: var(--dc-orange);
    box-shadow: 0 4px 10px rgba(255, 122, 61, .28);
}

.dc-c__range--disk::-moz-range-thumb {
    border-color: var(--dc-orange);
}

.dc-c__range-track {
    position: absolute;
    width: 100%;
    height: 6px;
    border-radius: 6px;
    background: #e9eef6;
    z-index: 1;
    overflow: hidden;
}

.dc-c__range-fill {
    height: 100%;
    border-radius: 6px;
    background: var(--dc-blue);
    transition: width .12s;
}

.dc-c__range-fill--ram {
    background: var(--dc-green);
}

.dc-c__range-fill--disk {
    background: var(--dc-orange);
}

.dc-c__slider-hint {
    margin-top: 10px;
    padding-left: 50px;
    font-size: 10.5px;
    color: var(--dc-muted-2);
    font-weight: 600;
    font-style: italic;
}

/* ── Selection card ────────────────────────────────────────────── */

.dc-c__selection-section {
    margin-top: -8px;
}

.dc-c__selection-card {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 16px;
    padding: 16px 18px;
    border-radius: 14px;
    border: 1.5px solid var(--dc-blue);
    background:
        radial-gradient(400px 120px at 100% 0%, rgba(29, 140, 240, .10), transparent 70%),
        linear-gradient(180deg, var(--dc-blue-soft-2) 0%, #fff 100%);
    box-shadow: 0 4px 14px rgba(29, 140, 240, .10);
}

.dc-c__sel-left {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.dc-c__sel-row-top {
    display: flex;
    align-items: center;
    gap: 8px;
}

.dc-c__sel-code {
    font-size: 11px;
    font-weight: 900;
    letter-spacing: .08em;
    color: var(--dc-blue-ink);
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 100px;
    background: var(--dc-blue-soft);
}

.dc-c__sel-tier {
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .06em;
    color: #fff;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 100px;
    background: var(--dc-muted);
}

.dc-c__sel-tier[data-tier="lite"]  { background: #6c7a93; }
.dc-c__sel-tier[data-tier="start"] { background: #19b893; }
.dc-c__sel-tier[data-tier="basic"] { background: #1d8cf0; }
.dc-c__sel-tier[data-tier="std"]   { background: #7c5cff; }
.dc-c__sel-tier[data-tier="pro"]   { background: #ff7a3d; }

.dc-c__sel-cfg {
    font-size: 13px;
    font-weight: 700;
    color: var(--dc-ink-2);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.005em;
}

.dc-c__sel-label {
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: .12em;
    color: var(--dc-muted);
    text-transform: uppercase;
    margin-top: 4px;
}

.dc-c__sel-desc {
    font-size: 13px;
    font-weight: 600;
    color: var(--dc-ink);
    line-height: 1.4;
}

.dc-c__sel-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 4px;
    border-left: 1px solid rgba(29, 140, 240, .18);
    padding-left: 16px;
    min-width: 130px;
}

.dc-c__sel-price {
    font-size: 28px;
    font-weight: 900;
    color: var(--dc-blue);
    line-height: 1;
    letter-spacing: -.02em;
    /* `align-items: baseline` puts all three children on the same text
     * baseline — the `$` glyph and `/mo` unit sit naturally inline with
     * the number instead of being parked at the top/bottom of the flex
     * box like the `flex-start` + `flex-end` mix did. */
    display: flex;
    align-items: baseline;
    gap: 1px;
    font-variant-numeric: tabular-nums;
}

.dc-c__sel-price sup {
    font-size: 13px;
    font-weight: 800;
    /* Lift the `$` glyph above the baseline like a native superscript would.
     * Flex baseline alignment ignores `vertical-align: super`, but a
     * `position: relative; bottom` offset still works inside flex items. */
    position: relative;
    bottom: 0.75em;
}

.dc-c__sel-price sub {
    font-size: 11px;
    font-weight: 700;
    color: var(--dc-muted);
}

/* ── Pill tabs (region + software category) ───────────────────── */

.dc-c__pill-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.dc-c__pill-tabs--sw {
    margin-bottom: 12px;
}

.dc-c__pill {
    padding: 7px 14px;
    border-radius: 100px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    font-size: 12px;
    font-weight: 600;
    color: var(--dc-muted);
    transition: all .15s;
}

.dc-c__pill:hover {
    border-color: var(--dc-blue);
    color: var(--dc-blue);
}

.dc-c__pill.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue);
    color: #fff;
    box-shadow: 0 4px 12px rgba(29, 140, 240, .25);
}

/* ── Location grid ────────────────────────────────────────────── */

.dc-c__loc-grid {
    display: grid;
    /* Same `minmax(0, 1fr)` trick: lets each tile shrink to the column width
     * and truncate the city span (`.dc-c__city` has overflow: ellipsis) rather
     * than enforcing min-content. Keeps the grid sized to its container. */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
    margin-top: 12px;
}

.dc-c__loc-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    transition: all .15s;
    font-size: 12px;
    font-weight: 600;
    color: var(--dc-ink-2);
    text-align: left;
    width: 100%;
}

/* Premium-location badge — a small amber "$" overhanging the top-right corner.
 * Only on tiles whose backend `features` include `elevated`. The overhang sits
 * outside the tile bounds; the .dc-c__grid wrapper's `overflow-clip-margin`
 * (added for the disabled-tile ping pulse) leaves room so it isn't clipped. */
.dc-c__loc-btn.is-premium { position: relative; }
.dc-c__loc-prem {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: linear-gradient(135deg, #f9c846, #e8910c);
    color: #fff;
    font: 800 10px/16px system-ui, sans-serif;
    text-align: center;
    box-shadow: 0 1px 2px rgba(180, 120, 0, .5);
    pointer-events: none;
}

.dc-c__loc-btn .dc-c__flag {
    font-size: 16px;
    line-height: 1;
}

.dc-c__loc-btn .dc-c__iso {
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: .06em;
    color: var(--dc-muted);
    padding: 2px 5px;
    border-radius: 4px;
    background: var(--dc-line-2);
    font-variant-numeric: tabular-nums;
    text-transform: uppercase;
}

/* `.dc-c__city` is a viewport: fixed-height flex item with `overflow:hidden`.
 * The actual text lives in a nested absolutely-positioned `.dc-c__city-text`
 * so the marquee animation (transform: translateX on the text) doesn't shift
 * the viewport itself — keeps the layout stable and prevents the text from
 * sliding under the ISO badge to the left. */
.dc-c__loc-btn .dc-c__city {
    flex: 1;
    min-width: 0;
    position: relative;
    overflow: hidden;
    /* Height matches the .dc-c__loc-btn font-size (12px) * line-height ~1.2.
     * Absolute-positioned children don't contribute to parent height, so we
     * set it explicitly. */
    height: 14px;
}

.dc-c__city-text {
    position: absolute;
    left: 0;
    top: 0;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* The default transition pads the start/end of the marquee animation. */
    transition: transform .12s linear;
}

/* Hover marquee — only fires when (a) the tile is hovered AND (b) the text
 * actually overflows. We drop max-width / overflow / text-overflow so the
 * full text becomes laid out and ready to slide; JS writes the exact
 * overflow distance into `--dc-marquee-shift` on the text span. */
.dc-c__loc-btn:hover .dc-c__city.is-overflow .dc-c__city-text {
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    animation: dc-c-marquee 4s ease-in-out infinite;
}

@keyframes dc-c-marquee {
    0%, 12%   { transform: translateX(0); }
    44%, 56%  { transform: translateX(var(--dc-marquee-shift, 0)); }
    88%, 100% { transform: translateX(0); }
}

/* Respect users who prefer no motion. */
@media (prefers-reduced-motion: reduce) {
    .dc-c__loc-btn:hover .dc-c__city.is-overflow .dc-c__city-text {
        animation: none;
    }
}

.dc-c__loc-btn:hover {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft-2);
}

.dc-c__loc-btn.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft);
    color: var(--dc-blue-ink);
    box-shadow: 0 0 0 3px rgba(29, 140, 240, .10);
}

.dc-c__loc-btn.is-active .dc-c__iso {
    background: rgba(29, 140, 240, .18);
    color: var(--dc-blue-ink);
}

/* Status dot at the right edge of each location tile (reference's `.ping`).
 *  - Default (active location, orderable): green
 *  - Disabled location (status='disabled', temporarily unavailable): red,
 *    plus a radar-style ring pulse on the right side of the dot to draw the
 *    eye to the unavailability without being noisy.
 * Selection is shown via the tile's border, not the ping colour. */
.dc-c__ping {
    margin-left: auto;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--dc-green);
    flex-shrink: 0;
    position: relative;
}

.dc-c__loc-btn.is-disabled .dc-c__ping {
    background: var(--dc-red);
}

/* Expanding-ring pulse on disabled tiles. The `::after` pseudo starts at the
 * dot's footprint and animates outward, fading as it grows. Layered behind
 * everything else so it never interferes with cursor / clicks. */
.dc-c__loc-btn.is-disabled .dc-c__ping::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--dc-red);
    opacity: 0.55;
    animation: dc-c-ping-pulse 1.6s ease-out infinite;
    pointer-events: none;
}

@keyframes dc-c-ping-pulse {
    0%   { transform: scale(1);   opacity: 0.55; }
    80%  { transform: scale(2.8); opacity: 0;    }
    100% { transform: scale(2.8); opacity: 0;    }
}

/* Disabled tile — visible but not orderable. We keep the `disabled` HTML
 * attribute for semantics (assistive tech announces the state), but Chromium
 * defaults disabled buttons to `pointer-events: none`, which would also
 * swallow our `cursor: not-allowed`. Restore pointer-events so the cursor
 * shows; the JS click handler already drops the event for disabled tiles. */
.dc-c__loc-btn.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: var(--dc-line-2);
    pointer-events: auto;
}

.dc-c__loc-btn.is-disabled:hover {
    border-color: var(--dc-line);
    background: var(--dc-line-2);
    transform: none;
}

/* Users who prefer reduced motion get a static red dot — meaning is preserved
 * (red = unavailable), only the pulse animation is suppressed. */
@media (prefers-reduced-motion: reduce) {
    .dc-c__loc-btn.is-disabled .dc-c__ping::after {
        animation: none;
        opacity: 0;
    }
}

.dc-c__loc-empty {
    grid-column: 1 / -1;
    padding: 18px 12px;
    border: 1px dashed var(--dc-line);
    border-radius: 12px;
    font-size: 12px;
    color: var(--dc-muted);
    text-align: center;
}

/* ── Toggle sections (OS / Software — mutually exclusive) ─────── */
/* Mirrors the reference v(1) UX: each section has a switch in its head; one
 * switch on locks the other section. When neither is on, neither selection
 * is sent in the order URL and the backend picks its default OS. */

.dc-c__section--toggle {
    border-top: 1px solid var(--dc-line);
    padding-top: 22px;
}

.dc-c__toggle-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 0;
    cursor: pointer;
    user-select: none;
}

.dc-c__toggle-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.dc-c__toggle-hint {
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .08em;
    color: var(--dc-muted);
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 100px;
    background: var(--dc-line-2);
}

.dc-c__section--toggle.is-on .dc-c__toggle-hint {
    background: rgba(29, 140, 240, .15);
    color: var(--dc-blue-ink);
}

.dc-c__section--toggle.is-on .dc-c__section-title {
    color: var(--dc-blue);
}

.dc-c__toggle-switch {
    width: 38px;
    height: 22px;
    border-radius: 100px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    position: relative;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background .15s, border-color .15s;
}

.dc-c__toggle-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--dc-muted-2);
    transition: left .18s, background .18s;
}

.dc-c__section--toggle.is-on .dc-c__toggle-switch {
    background: var(--dc-blue);
    border-color: var(--dc-blue);
}

.dc-c__section--toggle.is-on .dc-c__toggle-knob {
    left: 18px;
    background: #fff;
}

/* Body collapses with max-height transition (Chrome doesn't animate to auto).
 * Uses `overflow: clip` (vs. `hidden`) with `overflow-clip-margin` so the
 * disabled-tile hover card — which is absolutely positioned BELOW its tile
 * — can paint outside the clip box without being trimmed. `hidden` would
 * clip the popup the moment it crosses the toggle-body bottom edge; `clip`
 * + a generous margin lets the popup escape while still hiding the bulk of
 * the collapsed content during the open/close animation.
 *
 * `overflow-clip-margin` is only applied when the section is open. Chrome
 * respects it strictly even when `max-height: 0`, letting the OS grid (~90px
 * tall) paint into the margin and bleed through into the following section's
 * layout area. Safari is more lenient and effectively ignored the margin
 * for empty boxes, which is why the bug was Chrome-only. */
.dc-c__toggle-body {
    max-height: 0;
    overflow: clip;
    transition: max-height .28s ease, margin-top .28s ease;
}

.dc-c__section--toggle.is-on .dc-c__toggle-body {
    max-height: 1200px;
    margin-top: 14px;
    overflow-clip-margin: 120px;
}

.dc-c__toggle-subhint {
    margin-bottom: 12px;
}

/* When the OTHER section is on, this one greys out and ignores clicks (except
 * on its own head, so the user can still toggle it on without explicitly
 * turning off the active one — toggleSection() handles the switch). */
.dc-c__section--toggle.is-locked {
    opacity: .55;
    filter: grayscale(.9);
    pointer-events: none;
}

.dc-c__section--toggle.is-locked .dc-c__toggle-head {
    pointer-events: auto;
}

/* ── OS grid + version strip ──────────────────────────────────── */

.dc-c__os-grid {
    display: grid;
    grid-template-columns: repeat(8, minmax(0, 1fr));
    gap: 8px;
}

.dc-c__os-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    /* Tight horizontal padding so the icon viewport (`.dc-c__sg-icon`) can
     * stretch wide enough to render horizontal-logo sprites at a readable
     * scale without cropping. Tile still has comfortable vertical spacing. */
    padding: 12px 2px 10px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    transition: all .15s;
    width: 100%;
}

.dc-c__os-btn:hover {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft-2);
    transform: translateY(-1px);
}

.dc-c__os-btn.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft);
    box-shadow: 0 0 0 3px rgba(29, 140, 240, .10);
}

/* Solution icons reuse the `.select-group-{slug} .select-group__header:before`
 * rules from groups.css (same sprite + SVG set the /order/<uid> configurator
 * uses). groups.css sizes the icon at 64×64 (or wider/shorter for horizontal
 * logos like nginx/oracle) and assigns the background per slug. We add
 * `content`, fix the position, and apply a JS-computed transform (scale +
 * translate) that fits each logo into our square viewport regardless of its
 * intrinsic aspect ratio — see fitIconsIn() in constructor.js. */
/* The icon viewport stretches edge-to-edge inside the tile (its `.dc-c__os-btn`
 * / `.dc-c__sw-btn` parent), giving wide horizontal logos (nginx, opencart,
 * webasyst, …) enough room to render at a readable scale via proportional
 * fit, without needing per-slug bias overrides or cropping the wordmark.
 * Height 30px mirrors the original 18.05.2026 reference's `.os-btn img` size
 * so square icons (Ubuntu, WordPress, Docker, …) render at 30×30. */
.dc-c__sg-icon {
    position: relative;
    display: block;
    width: 100%;
    height: 30px;
    overflow: hidden;
    flex-shrink: 0;
}

/* Inner span groups.css expects to find. Visually inert by itself — only
 * its :before pseudo carries the icon. */
.dc-c__sg-icon .select-group__header {
    display: block;
    width: 100%;
    height: 100%;
    font-weight: normal;   /* override groups.css base `font-weight: bold` */
}

/* :before provides the icon. groups.css sets the per-slug width/height
 * (most icons are 64×64; some are wider like nginx 153×32, oracle 120×64,
 * tomcat 90×64 etc.) along with `background-size` / `background-position`
 * for sprite or SVG access. We only contribute:
 *
 *   - `content`  — groups.css declares it only inside
 *                  `.select-groups-software/.select-groups-soft`, which we
 *                  don't apply; without it `:before` doesn't render.
 *   - `position` — pin to top-left so transform-origin math works cleanly.
 *   - `transform` — scale + translate via CSS variables, which JS computes
 *                   per icon from the actual :before dimensions to keep
 *                   wide logos fully visible and centred in the tile.
 *
 * Deliberately NOT setting `width`/`height`/`background-*` — that would
 * override the per-slug rules from groups.css and clip wide icons or move
 * sprite offsets off-target. */
.dc-c__sg-icon .select-group__header:before {
    content: '';
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: auto;
    bottom: auto;
    background-repeat: no-repeat;
    transform: translate(var(--dc-icon-tx, 0), var(--dc-icon-ty, 0))
               scale(var(--dc-icon-scale, 0.46875));
    transform-origin: top left;
}

/* Safety baseline for icons whose groups.css rule omits width/height —
 * `.select-group-netbox` in particular only declares `background` and
 * relies on the configurator's `.select-groups-software` parent context
 * for the 64×64 base. Our markup doesn't include that parent class, so
 * we provide the default here. `:where()` drops this selector's
 * specificity to (0,1,1), letting per-slug rules like
 * `.select-group-nginx ... :before` (0,2,1) override width/height for
 * non-64×64 icons. */
:where(.dc-c__sg-icon) .select-group__header:before {
    width: 64px;
    height: 64px;
}

/* Per-slug size bias — multiplier applied to the JS-computed fit scale.
 *
 *   < 1.0 shrinks the icon, growing the surrounding tile whitespace.
 *   > 1.0 enlarges it past the viewport; the viewport's `overflow: hidden`
 *         trims the resulting overflow, so > 1 only looks right for icons
 *         whose source sprite has inner padding around the logo glyph.
 *
 * Convention: keep |bias-1| under ~0.2 — beyond that the trim removes
 * recognisable parts of the wordmark or the visual mismatch with sibling
 * tiles becomes obvious. */

/* -15% — wide sprite cells that scale up to the full viewport width and
 * end up visually heavier than neighbouring square logos. */
.dc-c__sg-icon.select-group-nginx,
.dc-c__sg-icon.select-group-lemp,
.dc-c__sg-icon.select-group-litespeed,
.dc-c__sg-icon.select-group-modx,
.dc-c__sg-icon.select-group-opencart,
.dc-c__sg-icon.select-group-webasyst,
.dc-c__sg-icon.select-group-mongodb,
.dc-c__sg-icon.select-group-blesta,
.dc-c__sg-icon.select-group-redmine,
.dc-c__sg-icon.select-group-csgo,
.dc-c__sg-icon.select-group-teamspeak,
.dc-c__sg-icon.select-group-rocket-chat {
    --dc-icon-bias: 0.85;
}

/* Reset the legacy `top: 60px` that groups.css applies to horizontal
 * wordmark logos. That offset was calibrated for the old 100px+ icon
 * container in the legacy configurator. Our `.dc-c__sg-icon` is only
 * 30px tall with `overflow: hidden`, so anything offset past it
 * disappears. Pin the wordmark to the top of our viewport — the JS
 * fit-icon logic then translates+scales it into the visible area. */
.dc-c__sg-icon.select-group-nginx .select-group__header:before,
.dc-c__sg-icon.select-group-lemp .select-group__header:before,
.dc-c__sg-icon.select-group-litespeed .select-group__header:before,
.dc-c__sg-icon.select-group-modx .select-group__header:before,
.dc-c__sg-icon.select-group-mongodb .select-group__header:before,
.dc-c__sg-icon.select-group-blesta .select-group__header:before,
.dc-c__sg-icon.select-group-csgo .select-group__header:before,
.dc-c__sg-icon.select-group-gitlab .select-group__header:before,
.dc-c__sg-icon.select-group-oracle .select-group__header:before,
.dc-c__sg-icon.select-group-opencart .select-group__header:before,
.dc-c__sg-icon.select-group-prometheus-grafana .select-group__header:before,
.dc-c__sg-icon.select-group-redmine .select-group__header:before,
.dc-c__sg-icon.select-group-webasyst .select-group__header:before {
    top: 0;
}

/* +15% — square sprite cells whose logo glyph sits inside generous source
 * padding; auto-fit makes them feel small next to siblings, the +15%
 * trim removes only the empty padding band. */
.dc-c__sg-icon.select-group-zabbix,
.dc-c__sg-icon.select-group-n8n {
    --dc-icon-bias: 1.15;
}

/* +10% — same idea for slightly wider icons (mssql is 79×64). */
.dc-c__sg-icon.select-group-mssql {
    --dc-icon-bias: 1.10;
}

/* Monogram fallback for solutions without a sprite class (unknown slug). */
.dc-c__sg-icon--monogram {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--dc-muted-2);
    color: #fff;
    font-size: 13px;
    font-weight: 800;
    border-radius: 8px;
}

.dc-c__sg-icon--monogram::before { content: none; }

.dc-c__os-btn img {
    width: 30px;
    height: 30px;
    object-fit: contain;
}

/* Label wrapper acts as a marquee viewport: single-line text, hidden
 * horizontal overflow, fixed height so tiles stay uniform regardless of
 * how long the underlying `software.name` happens to be. Long names
 * scroll horizontally on hover (handled by fitIconsIn / detectLabelOverflow
 * + the `dc-c-marquee` keyframes — same machinery used by the city tiles).
 *
 * `display: block` is needed because `<span>` is inline by default and
 * inline boxes ignore `width`/`overflow` — without it the wrapper would
 * collapse to its content width and starve the grid cell of intrinsic
 * min-width, making the entire grid look narrower. */
.dc-c__os-nm,
.dc-c__sw-nm {
    display: block;
    width: 100%;
    position: relative;
    overflow: hidden;
}

.dc-c__os-nm {
    height: 14px;
}

.dc-c__sw-nm {
    height: 13px;
}

.dc-c__os-nm-text,
.dc-c__sw-nm-text {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 700;
    color: var(--dc-muted);
    line-height: 1.25;
    transition: transform .12s linear;
}

.dc-c__os-nm-text { font-size: 10px; }
.dc-c__sw-nm-text { font-size: 9.5px; }

/* When the JS detector finds the text wider than its viewport it adds
 * `.is-overflow` on the wrapper. Switch from centered (transform:-50%) to
 * left-anchored layout so the marquee slides a known distance from start. */
.dc-c__os-nm.is-overflow .dc-c__os-nm-text,
.dc-c__sw-nm.is-overflow .dc-c__sw-nm-text {
    left: 0;
    transform: translateX(0);
}

/* On hover: drop the ellipsis / clip so the full text renders and starts
 * scrolling. dc-c-marquee animates translateX between 0 and the overflow
 * distance written into `--dc-marquee-shift` by detectLabelOverflow. */
.dc-c__os-btn:hover .dc-c__os-nm.is-overflow .dc-c__os-nm-text,
.dc-c__sw-btn:hover .dc-c__sw-nm.is-overflow .dc-c__sw-nm-text {
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    animation: dc-c-marquee 4s ease-in-out infinite;
}

.dc-c__os-btn.is-active .dc-c__os-nm-text {
    color: var(--dc-blue-ink);
}

.dc-c__ver-strip {
    margin-top: 12px;
    padding: 10px 12px;
    background: var(--dc-blue-soft-2);
    border: 1px dashed rgba(29, 140, 240, .30);
    border-radius: 12px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.dc-c__ver-strip[hidden] {
    display: none;
}

.dc-c__ver-label {
    font-size: 10px;
    font-weight: 800;
    color: var(--dc-blue-ink);
    letter-spacing: .10em;
    text-transform: uppercase;
    margin-right: 6px;
}

.dc-c__ver-btns {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.dc-c__ver-btn {
    padding: 5px 11px;
    border-radius: 100px;
    border: 1.5px solid #fff;
    background: #fff;
    font-size: 11px;
    font-weight: 600;
    color: var(--dc-muted);
    transition: all .12s;
    /* Anchor for the .dc-c__req-card hover popup on disabled tiles. */
    position: relative;
}

.dc-c__ver-btn:hover {
    color: var(--dc-blue);
    border-color: rgba(29, 140, 240, .30);
}

.dc-c__ver-btn.is-active {
    background: var(--dc-blue);
    border-color: var(--dc-blue);
    color: #fff;
}

/* ── Software ─────────────────────────────────────────────────── */

.dc-c__sw-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.dc-c__sw-clear {
    font-size: 10px;
    font-weight: 700;
    color: var(--dc-muted);
    padding: 4px 10px;
    border-radius: 100px;
    border: 1px solid var(--dc-line);
    background: #fff;
    letter-spacing: .05em;
    text-transform: uppercase;
    transition: all .15s;
}

.dc-c__sw-clear[hidden] {
    display: none;
}

.dc-c__sw-clear:hover {
    border-color: var(--dc-red);
    color: var(--dc-red);
}

.dc-c__sw-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 8px;
}

.dc-c__sw-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    /* See .dc-c__os-btn — tight horizontal padding lets the icon viewport
     * fill the tile width for horizontal logos. */
    padding: 10px 2px 8px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    position: relative;
    transition: all .15s;
    width: 100%;
}

.dc-c__sw-btn:hover {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft-2);
    transform: translateY(-1px);
}

.dc-c__sw-btn.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft);
    box-shadow: 0 0 0 3px rgba(29, 140, 240, .10);
}

.dc-c__sw-btn.is-active::after {
    content: '✓';
    position: absolute;
    top: 5px;
    right: 6px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--dc-blue);
    color: #fff;
    font-size: 9px;
    font-weight: 900;
    display: flex;
    align-items: center;
    justify-content: center;
}

.dc-c__sw-btn img {
    width: 28px;
    height: 28px;
    object-fit: contain;
}

.dc-c__sw-btn.is-active .dc-c__sw-nm-text {
    color: var(--dc-blue-ink);
}

.dc-c__sw-empty {
    grid-column: 1 / -1;
    padding: 18px 12px;
    border: 1px dashed var(--dc-line);
    border-radius: 12px;
    font-size: 12px;
    color: var(--dc-muted);
    text-align: center;
}

/* ── Requirements-driven disabled state (OS version + software tiles) ──
 *
 * Marked `is-disabled` by constructor.js when state.preset.cpu/ram/disk
 * doesn't satisfy `template.requirements`. The tile dims and shows the
 * "not allowed" cursor; on hover/focus, `.dc-c__req-card` reveals a
 * floating callout with a clickable link to the minimum compatible plan.
 *
 * IMPORTANT: dim the VISIBLE CHILDREN (icon + label), not the parent
 * button — `filter` or `opacity` on the button would cascade onto the
 * absolutely-positioned card inside and either make it semi-transparent
 * or, worse, create a stacking context that traps the card behind sibling
 * tiles in later grid rows (each disabled tile also creates one). */
.dc-c__ver-btn.is-disabled,
.dc-c__sw-btn.is-disabled {
    cursor: not-allowed;
    color: var(--dc-muted);
    /* Override the global `[aria-disabled="true"] { pointer-events: none; opacity: 0.35 }`
     * rule in common-justhost.css. Without restoring pointer-events here, the tile
     * can't receive :hover at all and the requirements hover-card never shows.
     * Opacity is restored to 1 here because we apply our own dimming via filter on
     * the icon + name children (see the next rule). */
    pointer-events: auto;
    opacity: 1;
}
.dc-c__sw-btn.is-disabled .dc-c__sg-icon,
.dc-c__sw-btn.is-disabled .dc-c__sw-nm {
    filter: grayscale(.55) opacity(.5);
}
.dc-c__ver-btn.is-disabled {
    opacity: .5;
    /* OS-version pills are tiny — dimming the whole pill is fine because
     * the popup card extends well outside the pill's bounds and isn't
     * visually multiplied with this opacity in any meaningful way. */
}
.dc-c__ver-btn.is-disabled:hover,
.dc-c__sw-btn.is-disabled:hover,
.dc-c__ver-btn.is-disabled:focus-within,
.dc-c__sw-btn.is-disabled:focus-within {
    /* Cancel the lift / background fill that the base :hover applies — a
     * disabled tile shouldn't visually invite a click. */
    transform: none;
    border-color: var(--dc-line);
    background: #fff;
    color: var(--dc-muted);
    /* CRITICAL: lift the hovered tile above its siblings so the card
     * popup can render OVER the next row of tiles. Position: relative
     * + explicit z-index creates a stacking context that contains the
     * card and rises above sibling tiles which sit at z-index: auto. */
    z-index: 10;
}
.dc-c__sw-btn.is-disabled:hover .dc-c__sg-icon,
.dc-c__sw-btn.is-disabled:hover .dc-c__sw-nm {
    filter: grayscale(.35) opacity(.7);
}
.dc-c__ver-btn.is-disabled:hover {
    opacity: .7;
}

.dc-c__req-card {
    position: absolute;
    left: 50%;
    /* Anchor BELOW the tile so the card doesn't overflow into the section
     * above (category pills, OS grid, etc.). The arrow flips to point up. */
    top: calc(100% + 6px);
    transform: translateX(-50%) translateY(-4px);
    width: max-content;
    max-width: 200px;
    padding: 8px 10px;
    border-radius: 10px;
    background: #1f2937;
    color: #fff;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.35;
    text-align: center;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s, transform .15s;
    z-index: 5;
}
/* Per CSS spec, `pointer-events: none` on a parent does NOT cascade to
 * descendants. The link inside defaults to `auto`, which would intercept
 * hovers from outside the tile (the link sits below the tile because the
 * card is anchored there) and trigger the parent's :hover, making the
 * card seem to "appear when hovering below the tile". Explicitly
 * resetting descendants closes that hole. */
.dc-c__req-card *,
.dc-c__req-card::before,
.dc-c__req-card::after {
    pointer-events: none;
}
/* Arrow pointing UP into the tile (card is below). */
.dc-c__req-card::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 0;
    height: 0;
    transform: translateX(-50%);
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-bottom: 6px solid #1f2937;
}
/* Invisible bridge filling the 6px gap between tile and card so cursor
 * can traverse without losing the tile's :hover state. */
.dc-c__req-card::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 10px;
}

/* Show the card on hover / focus-within of the disabled tile. Explicit
 * selectors (no :where()) keep specificity clear over the base hidden
 * state without needing `!important`. */
.dc-c__sw-btn.is-disabled:hover .dc-c__req-card,
.dc-c__sw-btn.is-disabled:focus-within .dc-c__req-card,
.dc-c__ver-btn.is-disabled:hover .dc-c__req-card,
.dc-c__ver-btn.is-disabled:focus-within .dc-c__req-card {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    pointer-events: auto;
}
/* Make the link and bridge interactive once the card is shown. */
.dc-c__sw-btn.is-disabled:hover .dc-c__req-card *,
.dc-c__sw-btn.is-disabled:hover .dc-c__req-card::before,
.dc-c__sw-btn.is-disabled:focus-within .dc-c__req-card *,
.dc-c__sw-btn.is-disabled:focus-within .dc-c__req-card::before,
.dc-c__ver-btn.is-disabled:hover .dc-c__req-card *,
.dc-c__ver-btn.is-disabled:hover .dc-c__req-card::before,
.dc-c__ver-btn.is-disabled:focus-within .dc-c__req-card *,
.dc-c__ver-btn.is-disabled:focus-within .dc-c__req-card::before {
    pointer-events: auto;
}

/* `.is-card-above` is added by JS (mouseenter handler in constructor.js) to
 * tiles that are too close to the bottom of the constructor box to fit the
 * card below them. Flip everything — card body, arrow direction, bridge
 * position, animation offset — so the popup appears ABOVE the tile instead. */
.dc-c__sw-btn.is-card-above .dc-c__req-card,
.dc-c__ver-btn.is-card-above .dc-c__req-card {
    top: auto;
    bottom: calc(100% + 6px);
    transform: translateX(-50%) translateY(4px);
}
.dc-c__sw-btn.is-card-above:hover .dc-c__req-card,
.dc-c__sw-btn.is-card-above:focus-within .dc-c__req-card,
.dc-c__ver-btn.is-card-above:hover .dc-c__req-card,
.dc-c__ver-btn.is-card-above:focus-within .dc-c__req-card {
    transform: translateX(-50%) translateY(0);
}
/* Arrow points DOWN when the card is above. */
.dc-c__sw-btn.is-card-above .dc-c__req-card::after,
.dc-c__ver-btn.is-card-above .dc-c__req-card::after {
    bottom: auto;
    top: 100%;
    border-top: 6px solid #1f2937;
    border-bottom: 0;
}
/* Bridge fills the gap on the other side. */
.dc-c__sw-btn.is-card-above .dc-c__req-card::before,
.dc-c__ver-btn.is-card-above .dc-c__req-card::before {
    bottom: auto;
    top: 100%;
}

.dc-c__req-card-text {
    display: block;
    color: rgba(255, 255, 255, .82);
    margin-bottom: 4px;
}

.dc-c__req-card-link {
    display: inline-block;
    color: #7fc6ff;
    font-weight: 700;
    text-decoration: none;
    border-bottom: 1px dashed rgba(127, 198, 255, .5);
    cursor: pointer;
}
.dc-c__req-card-link:hover {
    color: #fff;
    border-bottom-color: #fff;
}
.dc-c__req-card-link.is-nofit {
    color: rgba(255, 255, 255, .55);
    cursor: default;
    border-bottom: 1px dotted rgba(255, 255, 255, .25);
}

/* Inside the version strip, the tile is a tight pill — use a smaller gap
 * so the card hugs the button without leaving an obvious flicker gap. */
.dc-c__ver-btn.is-disabled .dc-c__req-card {
    top: calc(100% + 6px);
}

/* ───────────────────────── RIGHT COLUMN ─────────────────────────── */

.dc-c__right {
    display: flex;
    flex-direction: column;
    background:
        radial-gradient(600px 200px at 100% 0%, rgba(29, 140, 240, .08), transparent 60%),
        linear-gradient(180deg, #f7faff 0%, #ffffff 100%);
    border-left: 1px solid var(--dc-line);
}

.dc-c__summary {
    padding: 24px 22px 18px;
    border-bottom: 1px solid var(--dc-line);
}

.dc-c__summary-title {
    font-size: 14px;
    font-weight: 800;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--dc-blue-ink);
    margin-bottom: 12px;
}

.dc-c__spec-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 14px;
}

.dc-c__chip {
    display: inline-flex;
    align-items: center;
    padding: 6px 10px;
    border-radius: 100px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    font-size: 11px;
    font-weight: 700;
    color: var(--dc-ink);
}

.dc-c__chip--cpu {
    border-color: rgba(29, 140, 240, .25);
    background: var(--dc-blue-soft);
    color: var(--dc-blue-ink);
}

.dc-c__chip--ram {
    border-color: rgba(25, 184, 147, .25);
    background: rgba(25, 184, 147, .08);
    color: #0d8a6b;
}

.dc-c__chip--disk {
    border-color: rgba(255, 122, 61, .25);
    background: rgba(255, 122, 61, .08);
    color: #c25620;
}

.dc-c__srows {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.dc-c__srow {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
}

.dc-c__srow[hidden] {
    display: none;
}

.dc-c__sk {
    color: var(--dc-muted);
    font-weight: 500;
}

.dc-c__sv {
    font-weight: 700;
    color: var(--dc-ink-2);
    font-size: 12px;
    text-align: right;
    max-width: 170px;
}

.dc-c__sv--ok {
    color: var(--dc-green);
}

.dc-c__sv--accent {
    color: var(--dc-blue);
}

/* ── Period ───────────────────────────────────────────────────── */

.dc-c__period-block {
    padding: 18px 22px;
    border-bottom: 1px solid var(--dc-line);
}

.dc-c__period-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
}

.dc-c__pbtn {
    padding: 10px 4px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    transition: all .15s;
    text-align: center;
    position: relative;
}

.dc-c__pbtn:hover {
    border-color: var(--dc-blue);
}

.dc-c__pbtn.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue);
    color: #fff;
    box-shadow: 0 6px 14px rgba(29, 140, 240, .30);
}

.dc-c__pm {
    display: block;
    font-size: 12px;
    font-weight: 800;
    color: var(--dc-ink);
}

.dc-c__pbtn.is-active .dc-c__pm {
    color: #fff;
}

.dc-c__pd {
    display: block;
    font-size: 9px;
    font-weight: 700;
    color: var(--dc-green);
    margin-top: 2px;
    letter-spacing: .04em;
    min-height: 11px;
}

.dc-c__pbtn.is-active .dc-c__pd {
    color: rgba(255, 255, 255, .9);
}

.dc-c__period-custom-row {
    margin-top: 8px;
}

/* Specificity bump (see .dc-c__range above) to beat the theme-wide input rule. */
.dc-constructor input.dc-c__period-custom-input {
    width: 100%;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    color: var(--dc-ink);
    outline: none;
    transition: all .15s;
    font-variant-numeric: tabular-nums;
    margin: 0;
}

.dc-c__period-custom-input::placeholder {
    color: var(--dc-muted-2);
    font-weight: 500;
}

.dc-constructor input.dc-c__period-custom-input:focus {
    border-color: var(--dc-blue);
    box-shadow: 0 0 0 3px rgba(29, 140, 240, .12);
}

.dc-constructor input.dc-c__period-custom-input.is-active {
    border-color: var(--dc-blue);
    background: var(--dc-blue-soft-2);
    color: var(--dc-blue-ink);
}

.dc-c__period-custom-hint {
    font-size: 10px;
    color: var(--dc-muted-2);
    font-weight: 600;
    margin-top: 5px;
    text-align: center;
}

.dc-c__period-custom-hint.is-ok {
    color: var(--dc-green);
}

/* ── Promo ────────────────────────────────────────────────────── */

.dc-c__promo-block {
    padding: 14px 22px;
    border-bottom: 1px solid var(--dc-line);
}

.dc-c__promo-row {
    display: flex;
    gap: 6px;
}

/* Specificity bump (see .dc-c__range above) to beat the theme-wide input rule. */
.dc-constructor input.dc-c__promo-input {
    flex: 1;
    padding: 11px 14px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-line);
    background: #fff;
    font-family: inherit;
    font-size: 12px;
    font-weight: 700;
    color: var(--dc-ink);
    outline: none;
    transition: all .15s;
    text-transform: uppercase;
    letter-spacing: .06em;
    min-width: 0;
    width: auto;
    margin: 0;
}

.dc-c__promo-input::placeholder {
    color: var(--dc-muted-2);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}

.dc-constructor input.dc-c__promo-input:focus {
    border-color: var(--dc-blue);
    box-shadow: 0 0 0 3px rgba(29, 140, 240, .12);
}

.dc-constructor input.dc-c__promo-input.is-valid {
    border-color: var(--dc-green);
    background: rgba(25, 184, 147, .05);
    color: #0d8a6b;
}

.dc-constructor input.dc-c__promo-input.is-invalid {
    border-color: var(--dc-red);
    background: rgba(239, 79, 94, .04);
}

.dc-c__promo-apply {
    padding: 11px 16px;
    border-radius: 12px;
    border: 1.5px solid var(--dc-blue);
    background: var(--dc-blue);
    color: #fff;
    font-size: 12px;
    font-weight: 800;
    white-space: nowrap;
    transition: all .15s;
}

.dc-c__promo-apply:hover {
    background: var(--dc-blue-deep);
    border-color: var(--dc-blue-deep);
}

.dc-c__promo-msg {
    font-size: 10px;
    font-weight: 700;
    margin-top: 6px;
    min-height: 14px;
}

.dc-c__promo-msg.is-ok {
    color: var(--dc-green);
}

.dc-c__promo-msg.is-err {
    color: var(--dc-red);
}

/* ── Price ────────────────────────────────────────────────────── */

.dc-c__price-block {
    padding: 18px 22px 14px;
    border-bottom: 1px solid var(--dc-line);
}

.dc-c__disc-badges {
    display: flex;
    gap: 5px;
    margin-bottom: 6px;
    flex-wrap: wrap;
    min-height: 18px;
}

.dc-c__disc-badge {
    padding: 3px 9px;
    border-radius: 100px;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .03em;
    background: rgba(25, 184, 147, .12);
    color: #0d8a6b;
}

.dc-c__disc-badge[hidden] {
    display: none;
}

.dc-c__price-old {
    font-size: 13px;
    color: var(--dc-muted);
    text-decoration: line-through;
    margin-bottom: 4px;
    font-weight: 600;
}

.dc-c__price-old[hidden] {
    display: none;
}

.dc-c__price-main {
    font-size: 44px;
    font-weight: 900;
    color: var(--dc-blue);
    line-height: 1;
    letter-spacing: -.03em;
    /* See .dc-c__sel-price above — baseline alignment keeps `$`, value,
     * and `/mo` on one visual line instead of corner-parking the small bits. */
    display: flex;
    align-items: baseline;
    gap: 2px;
    font-variant-numeric: tabular-nums;
}

.dc-c__price-main sup {
    font-size: 18px;
    font-weight: 800;
    position: relative;
    bottom: 0.75em;
}

.dc-c__price-main sub {
    font-size: 13px;
    font-weight: 700;
    color: var(--dc-muted);
}

.dc-c__price-total {
    font-size: 11px;
    color: var(--dc-muted);
    font-weight: 600;
    margin-top: 6px;
}

/* ── Order button ─────────────────────────────────────────────── */

.dc-c__order-block {
    padding: 14px 22px 18px;
}

.dc-c__btn-order {
    width: 100%;
    padding: 16px;
    border-radius: 100px;
    border: none;
    background: linear-gradient(135deg, #1d8cf0 0%, #0a4fd4 100%);
    color: #fff;
    font-size: 14px;
    font-weight: 800;
    letter-spacing: .02em;
    box-shadow: 0 8px 22px rgba(29, 140, 240, .40);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: all .2s;
}

.dc-c__btn-order:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 28px rgba(29, 140, 240, .50);
}

.dc-c__btn-order:active {
    transform: translateY(0);
}

.dc-c__guarantee {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 12px;
    font-size: 10px;
    color: var(--dc-muted);
    font-weight: 600;
}

/* ── Responsive ───────────────────────────────────────────────── */

@media (max-width: 880px) {
    .dc-c__grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .dc-c__right {
        border-left: none;
        border-top: 1px solid var(--dc-line);
    }

    .dc-c__os-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .dc-c__sw-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .dc-c__loc-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dc-c__left {
        padding: 22px 18px;
        gap: 22px;
    }
}

@media (max-width: 520px) {
    .dc-c__slider-row {
        grid-template-columns: 32px 1fr 90px;
        gap: 10px;
    }

    .dc-c__selection-card {
        grid-template-columns: minmax(0, 1fr);
    }

    .dc-c__sel-right {
        border-left: none;
        border-top: 1px solid rgba(29, 140, 240, .18);
        padding-left: 0;
        padding-top: 10px;
        align-items: flex-start;
    }

    .dc-c__os-grid,
    .dc-c__sw-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
