/* The catalogue finder and the builder on a server's card. Loaded on those
   two pages only (layout.html), after site.css, whose tokens it is drawn
   with: nothing here is a new colour. Selected is navy; red stays with the
   orbit and the one button that orders. No inline styles anywhere — the CSP
   forbids them; what a script must place, it places through properties. */

/* What the finder and the builder hide must be gone wherever a class gives
   it a display of its own — a row on a phone is a grid. Only theirs: the
   rest of the page is not this file's (review 2026-10-07, K70). */
:is(.finder, .server, .sheet) [hidden], :is(.phone-bar, .buy-bar, .sheet)[hidden] { display: none !important; }

/* The head is kept short: every line above the panel is a row of the table
   pushed off the first screen. */
.finder.band-first { padding-top: 1rem; }
.finder .catalog-head { margin-bottom: 0.75rem; }
.finder .catalog-head h1 { font-size: var(--step-3); letter-spacing: -0.02em; line-height: 1.1; }
.finder .catalog-head .lead { margin-top: 0.3rem; max-width: none; font-size: var(--step--1); }
.finder .tabs { margin-bottom: 0.75rem; }
.finder .tab { padding-block: 0.4rem; }
.tab-ping { margin-left: 0.35rem; font-size: var(--step--2); white-space: nowrap; color: var(--text-2); }
.tab[aria-current="page"] .tab-ping { color: inherit; opacity: 0.85; }
.tab.is-zero { border-style: dashed; }

.finder-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip-inline { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

.text-btn {
    display: inline-block; padding: 0.25rem 0; border: 0; background: none; cursor: pointer;
    font-size: var(--step--1); font-weight: 500; color: var(--link);
    text-decoration: underline; text-decoration-color: var(--link-line); text-underline-offset: 0.2em;
}
.text-btn:hover { color: var(--link-hover); text-decoration-color: currentColor; }

/* ------------------------------------------------------------ the panel -- */
.console {
    padding: 1rem 1.25rem; border: 1px solid var(--hairline); border-radius: var(--r-lg);
    background: var(--bg-subtle);
}
.meter { min-width: 0; }
.meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; min-height: 1.5rem; margin-bottom: 0.15rem; }
.meter-name { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap; color: var(--text-2); }
.meter-read { font-family: var(--font-mono); font-size: var(--step--2); white-space: nowrap; color: var(--text-3); }
.meter.is-set .meter-read { font-weight: 600; color: var(--tint-text); }

.meter-steps { display: flex; }
.step {
    position: relative; display: grid; grid-template-rows: 1fr auto; justify-items: center; align-items: center;
    min-width: 2.75rem; height: 2.75rem; padding: 0.3rem 0.45rem 0.45rem; margin-left: -1px;
    border: 1px solid var(--border); background: var(--surface); cursor: pointer;
    font-family: var(--font-mono); transition: background 80ms linear;
}
.step:first-child { margin-left: 0; border-radius: var(--r-md) 0 0 var(--r-md); }
.step:last-child { border-radius: 0 var(--r-md) var(--r-md) 0; }
.step input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.step-v { font-size: var(--step--1); font-weight: 600; line-height: 1.1; white-space: nowrap; color: var(--text-strong); }
/* The number on a step. Its class was .step-n, which site.css has for the
   big numerals of "three steps" lists; their face, weight and margin came
   through. The look the page was approved with is written out here, under
   a name of its own (review 2026-10-07, K44). */
.step-count {
    display: block; margin-bottom: 0.75rem; font-family: var(--font-display); font-size: 0.75rem; font-weight: 800;
    letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--text-3);
}
/* The bar under a step: its share of what "any" would leave. */
.step-bar {
    position: absolute; left: 0; right: 0; bottom: 0; height: 3px; overflow: hidden; pointer-events: none;
    background: var(--border-strong); transform-origin: left center; transform: scaleX(var(--w, 0));
    transition: transform 80ms linear;
}
.step:hover { background: var(--surface-2); }
.step.is-in { background: var(--tint); }
.step.is-in .step-bar { background: var(--brand); }
.step.is-on { z-index: 1; border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.step.is-on .step-v { color: var(--tint-text); }
/* "Any" chosen is the panel at rest: grey, so that a set condition is the
   only blue on it. */
.step.is-any.is-on { border-color: var(--border-strong); box-shadow: none; background: var(--surface); }
.step.is-any.is-on .step-v { color: var(--text-strong); }
.step.is-zero { border-style: dashed; }
.step.is-zero .step-v, .step.is-zero .step-count { font-weight: 400; color: var(--text-3); }
.step:has(input:focus-visible) { z-index: 2; outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* "Within 12 hours" wears the colours of the mark it leaves in the rows. */
.step-fast .step-v::before {
    content: ""; display: inline-block; width: 0.45rem; height: 0.45rem; margin-right: 0.4rem; border-radius: 50%;
    vertical-align: 0.08em; background: var(--st-fast-dot);
}
.step-fast.is-on { border-color: var(--st-fast-dot); box-shadow: inset 0 0 0 1px var(--st-fast-dot); background: var(--st-fast-bg); }
.step-fast.is-on .step-v { color: var(--st-fast-fg); }
.step-fast.is-in .step-bar { background: var(--st-fast-dot); }

.budget-field {
    width: 8.25rem; height: 1.5rem; padding: 0 0.4rem; margin-left: auto;
    border: 1px solid var(--border-strong); border-radius: var(--r-sm); background: var(--surface);
    font-family: var(--font-mono); font-size: var(--step--2); text-align: right; color: var(--text-strong);
}
.budget-field::placeholder { color: var(--text-3); }
.budget-field:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.console-more[open] { flex: 1 0 100%; }
.console-more summary { display: inline-block; cursor: pointer; font-size: var(--step--1); font-weight: 500; color: var(--link); }
.console-more summary::after { content: " ▾"; content: " ▾" / ""; }
.console-more[open] summary::after { content: " ▴"; content: " ▴" / ""; }
.console-more .console-rows { margin-top: 0.75rem; }
.chipset { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.chipbox {
    position: relative; display: inline-flex; align-items: center; gap: 0.4rem; height: 2.75rem; padding: 0 0.7rem;
    border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); cursor: pointer;
    font-size: var(--step--1); color: var(--text-strong);
}
.chipbox input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chipbox.is-on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); background: var(--tint); color: var(--tint-text); }
.chipbox:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.chipbox-n { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-3); }

.console-foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1.25rem; margin-top: 0.6rem; }
.console-note { margin-right: auto; font-size: var(--step--2); color: var(--text-3); }

/* The form's own button is for a visitor without a script: with one, every
   choice is answered at once. */
html.js .console-apply { display: none; }

/* -------------------------------------------------------------- the tablo -- */
.tablo {
    position: sticky; top: var(--header-h); z-index: 20;
    display: flex; align-items: center; gap: 0.3rem 0.9rem; min-height: 3rem; padding: 0.3rem 0; margin-top: 0.75rem;
    border-bottom: 1px solid var(--hairline); background: var(--bg);
}
.tablo-count { display: inline-flex; align-items: center; gap: 0.5rem; flex: none; }
.tablo-count:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--r-sm); }
.ring { position: relative; display: grid; place-items: center; width: 4.4rem; height: 2.3rem; flex: none; }
.ring svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.ring-n {
    position: relative; font-family: var(--font-display); font-size: var(--step-0); font-weight: 700;
    font-variant-numeric: tabular-nums; letter-spacing: -0.01em; color: var(--text-strong);
}
.ring.is-zero .logo-orbit { fill: var(--border-strong); }
.tablo-of { font-size: var(--step--1); white-space: nowrap; color: var(--text-2); }
.tablo-from {
    flex: none; padding: 0.2rem 0; border: 0; background: none; cursor: pointer;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 700; font-variant-numeric: tabular-nums;
    white-space: nowrap; color: var(--text-strong);
    text-decoration: underline; text-decoration-color: var(--link-line); text-underline-offset: 0.22em;
}
.tablo-from:hover { color: var(--link-hover); text-decoration-color: currentColor; }
.tablo-chips { display: flex; flex: 1 1 auto; flex-wrap: wrap; gap: 0.3rem; min-width: 0; }
.cond {
    display: inline-flex; align-items: center; gap: 0.15rem; height: 1.75rem; padding-left: 0.6rem;
    border-radius: var(--r-pill); background: var(--tint);
    font-size: var(--step--2); font-weight: 600; white-space: nowrap; color: var(--tint-text);
}
.cond-fast { background: var(--st-fast-bg); color: var(--st-fast-fg); }
.cond-x {
    display: grid; place-items: center; width: 1.75rem; height: 1.75rem; padding: 0; border: 0; border-radius: 50%;
    background: none; cursor: pointer; color: inherit; text-decoration: none;
}
.cond-x::before { content: "×"; font-size: 1.05rem; line-height: 1; }
.cond-x:hover { background: color-mix(in srgb, currentColor 14%, transparent); }
.tablo .text-btn { flex: none; white-space: nowrap; }
.sort-select {
    height: 2rem; padding: 0 1.6rem 0 0.6rem; border: 1px solid var(--border); border-radius: var(--r-md);
    background-color: var(--surface); font-size: var(--step--2); color: var(--text-strong); cursor: pointer;
}
.tablo-sort { flex: none; margin-left: auto; }
.tablo-tool {
    flex: none; height: 2rem; padding: 0 0.65rem; border: 1px solid var(--border); border-radius: var(--r-md);
    background: var(--surface); font-size: var(--step--2); white-space: nowrap; color: var(--text-2); cursor: pointer;
}
html:not(.js) .tablo-tool { display: none; }
.tablo-tool:hover { border-color: var(--border-strong); color: var(--text-strong); }
.tablo-tool[aria-pressed="true"] { border-color: var(--brand); background: var(--tint); color: var(--tint-text); }

/* A narrow laptop: the conditions take a line of their own under the count. */
@media (min-width: 62rem) and (max-width: 79.99rem) {
    .tablo { flex-wrap: wrap; }
    .tablo-chips { order: 10; flex: 1 0 100%; }
}

.finder-caption { margin: 0.75rem 0 0.25rem; font-size: var(--step--2); color: var(--text-3); }

/* --------------------------------------------------------------- the table -- */
.finder .servers thead th {
    position: sticky; top: calc(var(--header-h) + var(--tablo-h, 3rem)); z-index: 10; background: var(--bg);
    box-shadow: inset 0 -1px 0 var(--hairline);
}
.th-sort {
    padding: 0; border: 0; background: none; cursor: pointer;
    font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit;
}
.th-sort { white-space: nowrap; }
.th-sort::after { content: " ↕"; content: " ↕" / ""; opacity: 0.6; }
th[aria-sort="ascending"] .th-sort, th[aria-sort="descending"] .th-sort { color: var(--text-strong); }
th[aria-sort="ascending"] .th-sort::after { content: " ↑"; content: " ↑" / ""; opacity: 1; }
th[aria-sort="descending"] .th-sort::after { content: " ↓"; content: " ↓" / ""; opacity: 1; }

/* A line's heading in one row: its tagline beside the name, not under it. */
@media (min-width: 62rem) {
    .finder .servers tr.line-row th { padding-block: 0.7rem; }
    .finder .servers .line-tagline { display: inline; margin-left: 0.75rem; letter-spacing: 0; }
}
.row-line, .row-good { display: none; margin-left: 0.5rem; vertical-align: 0.1em; }
.servers.is-flat .row-line, .servers.is-flat .row-good { display: inline-flex; }
.codes { margin-left: 0.4rem; font-family: var(--font-mono); font-size: 0.75rem; white-space: nowrap; color: var(--text-3); }
.price-more, .price-base { display: block; margin-top: 0.15rem; font-size: var(--step--2); white-space: nowrap; color: var(--text-3); }
/* The cells a condition lies on: what was asked for is marked in the answer. */
.finder .servers td.is-hit .v { padding: 0.1em 0.3em; margin: 0 -0.3em; border-radius: 3px; background: var(--mark-bg); }
.finder .servers td.num.is-hit .v { margin-right: 0; }

@container uc-rows (min-width: 52rem) {
    html.uc-dense .finder .servers tbody tr:not(.line-row) :is(th, td) { padding-block: 0.5rem; }
    html.uc-dense .finder .servers tbody th { font-size: var(--step--1); }
}

.servers tr.is-flash { background: var(--mark-bg); }
.finder-tail { margin-top: 1rem; font-size: var(--step--1); color: var(--text-3); }

/* --------------------------------------------- nothing fits; almost fits -- */
.nearest { margin-top: 1rem; padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--r-lg); }
.nearest-title { font-size: var(--step-2); }
.nearest-sub { margin-top: 0.4rem; color: var(--text-2); }
.nearest-list { margin-top: 1rem; border-block: 1px solid var(--hairline); }
.nearest-list li {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto; align-items: center; gap: 0.5rem 1.5rem;
    padding: 0.75rem 0; border-top: 1px solid var(--hairline);
}
.nearest-list li:first-child { border-top: 0; }
.nearest-what { font-weight: 600; color: var(--text-strong); }
.nearest-gain { font-size: var(--step--1); color: var(--text-2); }
.nearest-foot { margin-top: 1rem; font-size: var(--step--1); color: var(--text-3); }

.almost { margin-top: 1.5rem; padding: 1rem 1.25rem; border-radius: var(--r-lg); background: var(--bg-subtle); }
.almost-title { font-family: var(--font-text); font-size: var(--step--1); font-weight: 600; letter-spacing: 0; color: var(--text-2); }
.almost-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 1rem; margin-top: 0.4rem; font-size: var(--step--1); color: var(--text); }

/* ----------------------------------------------------------- rail on the left -- */
/* The finder is a rail on the left, and it is put away by default: the page
   opens as the plain table with one bar above it. The bar's first button
   brings the rail out; opened, the button is the rail's own header. */
.tablo-rest { display: contents; }
.rail-toggle { display: none; }
/* With a script the finder is out of sight until its button is pressed —
   on a phone until its sheet is opened. Without one it stands above the table. */
html.js .finder .console-slot { display: none; }
@media (min-width: 62rem) {
    .finder[data-layout="rail"] .tablo { margin-top: 0; gap: 0.3rem 2rem; }
    .finder[data-layout="rail"] .tablo-rest { display: flex; flex: 1 1 auto; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.9rem; min-width: 0; }

    html.js .finder[data-layout="rail"] .rail-toggle {
        display: inline-flex; flex: none; align-items: center; gap: 0.55rem; height: 2.25rem; padding: 0 0.9rem 0 0.7rem;
        border: 1px solid var(--brand); border-radius: var(--r-md); background: var(--surface);
        font-size: var(--step--1); font-weight: 600; white-space: nowrap; color: var(--brand); cursor: pointer;
        transition: background var(--dur-1), color var(--dur-1);
    }
    html.js .finder[data-layout="rail"] .rail-toggle:hover { background: var(--tint); }
    .rail-toggle svg { flex: none; width: 1.1rem; height: 1.1rem; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
    /* how many conditions are in force while the rail is out of sight */
    .rail-n {
        display: grid; place-items: center; min-width: 1.3rem; height: 1.3rem; padding: 0 0.3rem; border-radius: var(--r-pill);
        background: var(--primary); font-family: var(--font-mono); font-size: 0.75rem; font-weight: 600; color: var(--on-primary);
    }
    .rail-hide { display: none; margin-left: auto; font-weight: 400; color: var(--text-2); }
    .rail-hide::after { content: " ‹"; content: " ‹" / ""; }
    /* opened: the button spans the rail and reads as its header */
    html.js.uc-rail-open .finder[data-layout="rail"] .rail-toggle { width: 17.5rem; border-color: var(--hairline); background: var(--bg-subtle); color: var(--text-strong); }
    html.js.uc-rail-open .finder[data-layout="rail"] .rail-toggle:hover { border-color: var(--border-strong); background: var(--bg-subtle); }
    html.uc-rail-open .rail-hide { display: inline; }

    .finder[data-layout="rail"] .finder-body { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; column-gap: 2rem; }
    html.uc-rail-open .finder[data-layout="rail"] .finder-body { grid-template-columns: 17.5rem minmax(0, 1fr); }
    html.js.uc-rail-open .finder[data-layout="rail"] .console-slot { display: block; }
    .finder[data-layout="rail"] .console-slot {
        position: sticky; top: calc(var(--header-h) + var(--tablo-h, 3rem) + 0.75rem);
        max-height: calc(100dvh - var(--header-h) - var(--tablo-h, 3rem) - 1.5rem); margin-top: 0.75rem; overflow: auto; scrollbar-width: thin;
    }
    .finder[data-layout="rail"] .console { padding: 1rem; }
    .finder[data-layout="rail"] .console-rows { display: grid; gap: 0.9rem; }
    .finder[data-layout="rail"] .meter-steps { display: grid; grid-template-columns: repeat(auto-fill, minmax(3.1rem, 1fr)); gap: 0.25rem; }
    .finder[data-layout="rail"] .step { min-width: 0; height: 2.5rem; margin-left: 0; border-radius: var(--r-md); }
    .finder[data-layout="rail"] .step.is-any { grid-column: span 2; }
    .finder[data-layout="rail"] .step-fast { grid-column: span 3; }
    .finder[data-layout="rail"] .console-foot { flex-direction: column; }
    .finder[data-layout="rail"] .console-more .console-rows { display: grid; }
    /* With the rail out the table gives up one column: the channel. Put
       away, the table is the one the site has today. */
    html.uc-rail-open .finder[data-layout="rail"] .servers-hub { table-layout: auto; }
    html.uc-rail-open .finder[data-layout="rail"] .servers-hub :is(th, td):nth-child(5) { display: none; }
    html.uc-rail-open .finder[data-layout="rail"] .servers-hub th:nth-child(n) { width: auto; }
    /* the narrower table lets the name wrap, not the figures */
    html.uc-rail-open .finder[data-layout="rail"] .servers-hub td:is(:nth-child(2), :nth-child(3)) { white-space: nowrap; }
}

/* The rail slides out from under its button and pushes the table aside. The
   browser moves pictures of the two states, so the table is not laid out
   anew on every frame; the pictures keep their scale and are clipped rather
   than squeezed. The names live only while this move lasts. */
html.uc-rail-move .rail-toggle { view-transition-name: uc-toggle; }
html.uc-rail-move .tablo-rest { view-transition-name: uc-tablo; }
html.uc-rail-move .console-slot { view-transition-name: uc-rail; }
html.uc-rail-move .finder-main { view-transition-name: uc-main; }
html.uc-rail-move::view-transition-old(root) { display: none; }
html.uc-rail-move::view-transition-new(root) { animation: none; }
html.uc-rail-move::view-transition-group(*) { animation-duration: 280ms; animation-timing-function: var(--ease-out); }
html.uc-rail-move::view-transition-group(uc-main), html.uc-rail-move::view-transition-group(uc-tablo) { overflow: clip; }
html.uc-rail-move::view-transition-old(uc-main), html.uc-rail-move::view-transition-new(uc-main),
html.uc-rail-move::view-transition-old(uc-tablo), html.uc-rail-move::view-transition-new(uc-tablo) {
    width: 100%; height: 100%; object-fit: none; object-position: left top; animation-duration: 200ms;
}
html.uc-rail-move::view-transition-old(uc-toggle), html.uc-rail-move::view-transition-new(uc-toggle) { height: 100%; object-fit: cover; object-position: left center; }
html.uc-rail-move::view-transition-new(uc-rail):only-child { animation: uc-rail-in 280ms var(--ease-out) both; }
html.uc-rail-move::view-transition-old(uc-rail):only-child { animation: uc-rail-out 180ms ease-in both; }
@keyframes uc-rail-in { from { opacity: 0; transform: translateX(-2rem); } }
@keyframes uc-rail-out { to { opacity: 0; transform: translateX(-2rem); } }

/* -------------------------------------------------------------- the phone -- */
.phone-bar, .sheet:not([open]) { display: none; }
@media not all and (min-width: 62rem) {
    .finder .catalog-head .lead { display: none; }
    /* Countries in one row that scrolls sideways, to the edge of the screen. */
    .finder .tabs { flex-wrap: nowrap; margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); overflow-x: auto; scrollbar-width: none; }
    .finder .tabs::-webkit-scrollbar { display: none; }
    .finder .tab { flex: none; }
    .tablo { flex-wrap: wrap; top: var(--header-h); }
    html.js .tablo-sort, .tablo-tool { display: none; }
    .tablo-chips { flex: 1 0 100%; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }

    .phone-bar:not([hidden]) {
        position: fixed; inset: auto 0 0; z-index: 40; display: flex; gap: 0.5rem;
        padding: 0.5rem var(--gutter) calc(0.5rem + env(safe-area-inset-bottom));
        border-top: 1px solid var(--border); background: var(--surface);
    }
    .phone-open { flex: 1 1 50%; }
    .phone-bar .sort-select { flex: 1 1 50%; height: 2.75rem; font-size: 1rem; }

    .sheet[open] { display: flex; }
    .sheet {
        flex-direction: column; width: 100%; max-width: 100%; max-height: 88dvh; margin: auto 0 0; padding: 0;
        border: 0; border-top: 1px solid var(--border); border-radius: 1rem 1rem 0 0; background: var(--surface); color: var(--text);
    }
    .sheet::backdrop { background: rgb(16 20 59 / 0.45); }
    .sheet-head { display: flex; align-items: center; gap: 1rem; padding: 0.75rem var(--gutter); border-bottom: 1px solid var(--hairline); }
    .sheet-head h2 { margin-right: auto; font-size: var(--step-1); }
    .sheet-reset { padding: 0.5rem 0; border: 0; background: none; font-size: var(--step--1); color: var(--link); text-decoration: underline; }
    .sheet-close { width: 2.75rem; height: 2.75rem; font-size: 1.1rem; }
    .sheet-body { flex: 1 1 auto; overflow: auto; overscroll-behavior: contain; }
    .sheet-foot { padding: 0.75rem var(--gutter) calc(0.75rem + env(safe-area-inset-bottom)); border-top: 1px solid var(--hairline); }
    .sheet-foot .btn { width: 100%; height: auto; min-height: 3.25rem; white-space: normal; }

    .console { padding: 1rem var(--gutter); border: 0; border-radius: 0; background: none; }
    .console-rows { display: grid; gap: 1.1rem; }
    /* Steps on an even grid, so that the last of a scale does not stretch
       across a row of its own. */
    .meter-steps { display: grid; grid-template-columns: repeat(auto-fill, minmax(3.4rem, 1fr)); gap: 0.3rem; }
    .step { min-width: 0; height: 2.9rem; margin-left: 0; border-radius: var(--r-md); }
    .step.is-any { grid-column: span 2; }
    .step-fast { grid-column: span 3; }
    .budget-field { height: 2.25rem; font-size: 1rem; }
    .console-foot .text-btn { display: none; }

    .nearest { padding: 1rem; }
    .nearest-list li { grid-template-columns: 1fr; gap: 0.3rem; }
    .nearest-list .btn { justify-self: start; }
}

/* ------------------------------------------------- the table and its room -- */
/* The table is laid out for the room it has, whatever took the rest: a
   narrow window, a phone, the rail pushed out beside it. Short of room for
   all its columns it gives up the channel and lets the "faster" line wrap:
   six columns then need about 790px in Ukrainian and 810px in English.
   Short of that, a server is three lines: name and price; cores, memory,
   drives; delivery and channel. Nothing is ever cut off at the edge
   (review 2026-10-07, K05). */
.finder-main { container: uc-rows / inline-size; }
@container uc-rows (max-width: 59.99rem) {
    .servers-hub { table-layout: auto; }
    .servers-hub :is(th, td):nth-child(5) { display: none; }
    .servers-hub th:nth-child(n) { width: auto; }
    .servers-hub td:is(:nth-child(2), :nth-child(3)) { white-space: nowrap; }
    .servers-hub .delivery-faster { white-space: normal; }
}
@container uc-rows (max-width: 51.99rem) {
    /* The head goes with the columns; the order is chosen above the table. */
    .finder .servers thead { display: none; }
    .finder .servers, .finder .servers tbody { display: block; }
    .finder .servers tbody tr:not(.line-row) {
        display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; align-items: baseline; gap: 0.25rem 0.6rem; padding: 0.8rem 0;
    }
    .finder .servers tbody tr[hidden] { display: none; }
    .finder .servers tbody :is(th, td) { display: block; padding: 0; text-align: left; }
    .finder .servers tbody td::before { content: none; }
    .finder .servers tbody th[scope="row"] { grid-column: 1 / 4; margin: 0; }
    /* The price stands beside the name; what goes with it — how many more
       configurations, the price without conditions — takes lines of its own
       under the row, so that a long note never squeezes the drives. */
    .finder .servers tbody td.num { display: contents; }
    .finder .servers tbody td.num > :first-child { grid-area: 1 / 4; justify-self: end; }
    .finder .servers tbody td.num > .price-more { grid-area: 4 / 1 / auto / -1; margin: 0; }
    .finder .servers tbody td.num > .price-base { grid-area: 5 / 1 / auto / -1; margin: 0; }
    .finder .servers tbody td:nth-child(2) { grid-area: 2 / 1; }
    .finder .servers tbody td:nth-child(3) { grid-area: 2 / 2; }
    .finder .servers tbody td:nth-child(4) { grid-area: 2 / 3; }
    .finder .servers tbody td:nth-child(6) { grid-area: 3 / 1 / auto / 4; }
    .finder .servers tbody td:nth-child(5) { grid-area: 3 / 4; justify-self: end; color: var(--text-3); }
    .finder .servers tbody td:is(:nth-child(2), :nth-child(3))::after { content: " ·"; color: var(--text-3); }
    .finder .servers tr.line-row { display: block; position: sticky; top: calc(var(--header-h) + var(--tablo-h, 3rem)); z-index: 5; padding: 0.6rem 0; }
    .finder .servers tr.line-row th { padding: 0; font-size: var(--step-1); }
    .finder .servers .line-tagline { display: none; }
    .row-line, .row-good { margin: 0.2rem 0.4rem 0 0; }
    .servers.is-flat .row-line { display: inline-flex; }
    .servers.is-flat .row-good { display: none; }
    .finder .servers .server-link { display: block; }
    .delivery-faster, .price-more, .price-base { white-space: normal; }
    /* the channel has its place in the third line again — beside the rail
       too, where the table as a table gives the column up */
    .finder .servers-hub tbody td:nth-child(5),
    html.uc-rail-open .finder[data-layout="rail"] .servers-hub tbody td:nth-child(5) { display: block; }
}

/* ------------------------------------------------------------------ motion -- */
/* Rows travel to their new places; the rest of the page changes at once. */
html.uc-rows::view-transition-group(*) { animation-duration: 240ms; animation-timing-function: var(--ease-out); }
html.uc-rows::view-transition-old(root) { display: none; }
html.uc-rows::view-transition-new(root) { animation: none; }
@media (prefers-reduced-motion: reduce) {
    .step, .step-bar { transition: none; }
}

/* =================================================================== */
/* The builder on a server's card.                                       */
/* =================================================================== */


/* where the visitor came from */
.ctx {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 1.25rem; margin-bottom: 1.5rem; padding: 0.6rem 0.9rem;
    border-radius: var(--r-md); background: var(--tint); font-size: var(--step--1); color: var(--tint-text);
}
.ctx-fit { font-family: var(--font-mono); font-size: var(--step--2); }
.ctx-back { margin-left: auto; white-space: nowrap; }

/* Where scripts run, the table of configurations is kept back while the
   builder is on its way, and its room held, so that the card does not show
   a table only to fold it a moment later. If the builder does not come —
   no file, an old one, a script that failed — the card says so to itself
   (.is-plain, see uc-server.js and theme.js) and the table is the card. */
.build-wait { display: none; }
html.js #card[data-catalog]:not(.is-built):not(.is-plain) .build-wait { display: block; min-height: 20rem; }
html.js #card[data-catalog]:not(.is-built):not(.is-plain) #order-form > :is(.table-wrap, details.more-configs) { display: none; }

.build { display: grid; gap: 1.25rem; }
.build-only, .build-fixed { font-size: var(--step-0); color: var(--text); }
.build-fixed .meter-name { margin-right: 0.75rem; }

.build-notice {
    padding: 0.6rem 0.8rem; border-radius: var(--r-md); background: var(--st-slow-bg);
    font-size: var(--step--1); color: var(--st-slow-fg);
}
.build-notice .text-btn { color: inherit; text-decoration-color: currentColor; }
.server > .wrap > .build-notice { margin-bottom: 1.5rem; }

/* ------------------------------------------------------------ quick picks -- */
.quick { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0.5rem; }
.quick-name { align-self: center; margin-right: 0.25rem; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-2); }
.quick-btn {
    display: grid; gap: 0.1rem; padding: 0.45rem 0.8rem; border: 1px solid var(--border); border-radius: var(--r-md);
    background: var(--surface); text-align: left; cursor: pointer; transition: border-color var(--dur-1), background var(--dur-1);
}
.quick-btn:hover { border-color: var(--border-strong); }
.quick-what { font-size: var(--step--1); font-weight: 600; color: var(--text-strong); }
.quick-cfg { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-3); }
.quick-fast .quick-what::before {
    content: ""; display: inline-block; width: 0.45rem; height: 0.45rem; margin-right: 0.4rem; border-radius: 50%;
    vertical-align: 0.08em; background: var(--st-fast-dot);
}
.quick-btn[aria-pressed="true"] { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); background: var(--tint); }
.quick-btn[aria-pressed="true"] .quick-what { color: var(--tint-text); }

/* ---------------------------------------------------------------- memory -- */
.build-ram .meter-steps { flex-wrap: wrap; row-gap: 0.3rem; }
.build-step {
    grid-template-rows: auto auto auto; align-content: center; row-gap: 0.15rem;
    min-width: 5rem; height: 4rem; padding: 0.4rem 0.6rem;
}
.build-step .step-v { font-size: var(--step--1); }
.build-step .step-count { white-space: nowrap; }
.build-step.is-on .step-count { color: var(--tint-text); }
.build-step.is-on { background: var(--tint); }
/* Picking it will move the other axis: said before the click, not after. */
.build-step.is-shift { border-style: dashed; }
.build-step.is-shift .step-v { font-weight: 400; color: var(--text-2); }
.step-fastmark { font-size: 0.6875rem; line-height: 1; color: var(--st-fast-fg); }
.step-fastmark::before {
    content: ""; display: inline-block; width: 0.4rem; height: 0.4rem; margin-right: 0.25rem; border-radius: 50%; background: var(--st-fast-dot);
}
/* The steps that answer the request the visitor came with. */
.build-step.in-pick::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--brand); }
.pick-note { margin-top: 0.35rem; font-size: 0.75rem; color: var(--text-3); }

/* ---------------------------------------------------------------- drives -- */
.drive-body { display: flex; align-items: flex-start; gap: 1.5rem; }
.drive-col { flex: 1 1 auto; min-width: 0; }
.drive-heads { display: grid; grid-template-columns: 6rem 7.5rem; padding-right: 0.5rem; font-size: 0.75rem; text-align: right; color: var(--text-3); }
.drive-list { border-top: 1px solid var(--hairline); }
.drive {
    position: relative; display: grid; grid-template-columns: 1.4rem minmax(0, 1fr) 6rem 7.5rem; align-items: center;
    min-height: 2.5rem; padding: 0.3rem 0.5rem 0.3rem 0.6rem; border-bottom: 1px solid var(--hairline);
    font-size: var(--step--1); cursor: pointer; transition: background var(--dur-1);
}
.drive:hover { background: var(--bg-subtle); }
.drive input { width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--primary); cursor: pointer; }
.drive-what { min-width: 0; overflow-wrap: anywhere; font-family: var(--font-mono); font-size: 0.92em; color: var(--text-strong); }
.drive-note { margin-left: 0.6rem; font-family: var(--font-text); font-size: 0.75rem; color: var(--text-3); }
.drive-note.is-fast { color: var(--st-fast-fg); }
.drive-cap, .drive-delta { font-family: var(--font-mono); font-size: 0.92em; text-align: right; white-space: nowrap; color: var(--text-2); }
.drive-delta { font-weight: 600; color: var(--text-strong); }
.drive.is-on { background: var(--tint); box-shadow: inset 3px 0 0 var(--brand); }
.drive.is-on .drive-delta { font-weight: 400; color: var(--tint-text); }
.drive.is-shift .drive-what { color: var(--text-2); }
.drive.is-shift { border-bottom-style: dashed; }
.drive:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

.away { font-size: var(--step--1); color: var(--text-2); }
.away-name { color: var(--text-3); }

/* ------------------------------------------------------------------ map -- */
.avail { flex: none; }
.avail-grid {
    display: grid; grid-template-columns: repeat(var(--cols), 1.75rem); grid-auto-rows: calc(2.5rem + 1px);
    grid-template-rows: 1.65rem; border-top: 1px solid transparent;
}
.avail-top { align-self: end; padding-bottom: 0.3rem; font-family: var(--font-mono); font-size: 0.6875rem; text-align: center; color: var(--text-3); }
.avail-cell {
    position: relative; display: grid; place-items: center; padding: 0; border: 0; border-bottom: 1px solid var(--hairline);
    background: none; cursor: pointer;
}
.avail-cell:disabled { cursor: default; }
.avail-cell::before, .avail-key::before { content: ""; display: block; box-sizing: border-box; }
/* The sign differs by shape, not by colour alone. */
.avail-fast::before { width: 0.7rem; height: 0.7rem; border: 2px solid var(--bg); border-radius: 50%; background: var(--st-fast-dot); box-shadow: 0 0 0 1.5px var(--st-fast-dot); }
.avail-slow::before { width: 0.35rem; height: 0.35rem; border-radius: 50%; background: var(--st-slow-dot); }
.avail-away::before { width: 0.55rem; height: 0.55rem; border: 1.5px solid var(--text-3); border-radius: 50%; }
.avail-none::before { width: 0.4rem; height: 0; border-top: 1.5px solid var(--border-strong); }
.avail-cell.in-pick { background: var(--bg-subtle); }
.avail-cell.is-row, .avail-cell.is-col { background: var(--tint); }
.avail-cell.is-on { z-index: 1; box-shadow: inset 0 0 0 2px var(--brand); }
.avail-cell:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--border-strong); }
.avail-cell.is-on:hover { box-shadow: inset 0 0 0 2px var(--brand); }
.avail-legend { display: flex; flex-wrap: wrap; gap: 0.2rem 0.9rem; max-width: 16rem; margin-top: 0.6rem; font-size: 0.75rem; color: var(--text-3); }
.avail-key { display: inline-flex; align-items: center; gap: 0.4rem; }
.avail-info { max-width: 16rem; min-height: 2.4em; margin-top: 0.4rem; font-size: 0.75rem; color: var(--text-2); }

/* -------------------------------------------------------------- summary -- */
.build-card .price-card-label { margin-bottom: 0.25rem; }
.dial { position: relative; margin: 0.5rem 0.5rem 0.25rem; }
.dial-ring { display: block; width: 100%; height: auto; overflow: visible; }
.dial-ring .logo-orbit { fill: var(--orbit); }
.dial-tick { stroke: var(--border-strong); stroke-width: 0.7; stroke-linecap: round; }
.dial-fast { fill: var(--st-fast-dot); }
/* The mark of the chosen price. It is a reading, not a handle: no shadow,
   no answer to the pointer. */
.dial-sat { fill: var(--brand); stroke: var(--surface); stroke-width: 2; }
.dial-price {
    position: absolute; inset: 0; display: grid; grid-auto-flow: column; place-content: center; align-items: baseline;
    font-family: var(--font-display); font-size: var(--step-3); font-weight: 700; letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums; color: var(--text-strong); pointer-events: none;
    /* Where the price crosses the ring it keeps a margin of the card's own
       colour. A shadow rather than a stroke: a stroke is drawn glyph by
       glyph and bites into the neighbouring digit. */
    text-shadow: 0 0 3px var(--surface), 0 0 3px var(--surface), 0 0 3px var(--surface), 0 0 6px var(--surface), 0 0 6px var(--surface), 0 0 10px var(--surface);
}
.dial-price .price-per { margin-left: 0.2rem; font-size: var(--step--1); }
.dial-range { margin: -0.25rem 0 0.75rem; font-family: var(--font-mono); font-size: 0.75rem; text-align: center; color: var(--text-3); }
.build-card.is-single :is(.dial-ticks, .dial-sat) { display: none; }

.build-sum { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.35rem 0.9rem; margin: 0.9rem 0; padding-top: 0.9rem; border-top: 1px solid var(--hairline); font-size: var(--step--1); }
.build-sum dt { color: var(--text-3); }
.build-sum dd { margin: 0; color: var(--text-strong); border-radius: 3px; }
.build-sum dd.is-flash { animation: uc-flash 600ms ease-out; }
@keyframes uc-flash { from { background: var(--mark-bg); } to { background: transparent; } }
.build-status { margin-bottom: 0.25rem; font-size: var(--step--1); font-weight: 500; color: var(--st-fast-fg); }
.build-status.is-out { color: var(--st-slow-fg); }
.build-card .build-notice { margin-bottom: 0.75rem; }
.build-card > .text-btn { display: block; margin-top: 0.5rem; }

.server.is-built .more-configs { margin-top: 1.5rem; }
/* The table under one fold: what was folded inside it before stays open. */
.server.is-built .build-all > .more-configs { margin-top: 0; }
.build-all > .more-configs > summary { display: none; }
.order-yours { margin-bottom: 0.5rem; font-weight: 600; color: var(--text-strong); }

/* ---------------------------------------------------------------- phone -- */
.buy-bar { display: none; }
@media not all and (min-width: 62rem) {
    .ctx-back { margin-left: 0; }
    .build-step { flex: 1 0 30%; min-width: 0; margin-left: 0; border-radius: var(--r-md); }
    .build-ram .meter-steps { display: flex; gap: 0.3rem; }
    .drive-body { display: block; }
    .avail { display: none; }
    .drive { grid-template-columns: 1.6rem minmax(0, 1fr) auto; min-height: 3rem; }
    .drive-cap { display: none; }
    .drive-heads { display: none; }
    .drive-note { display: block; margin: 0.1rem 0 0; }
    .buy-bar:not([hidden]) {
        position: fixed; inset: auto 0 0; z-index: 40; display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
        padding: 0.5rem var(--gutter) calc(0.5rem + env(safe-area-inset-bottom));
        border-top: 1px solid var(--border); background: var(--surface);
    }
    .buy-what { display: grid; gap: 0.15rem; justify-items: start; }
    .buy-price { font-family: var(--font-display); font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-strong); }
}
@media (prefers-reduced-motion: reduce) {
    .build-sum dd.is-flash { animation: none; }
}

/* What a scale's numbers mean, said under it where every visitor can read
   it, not in a tooltip (review 2026-10-07, K19). */
.meter-hint { margin: 0.35rem 0 0; font-size: var(--step--2); line-height: 1.35; color: var(--text-3); }

/* What is sold only in another country, past the first few: unfolded on
   request, every one a link (review 2026-10-07, K49). */
.away-more { margin-top: 0.35rem; font-size: var(--step--1); color: var(--text-2); }
.away-more > summary { cursor: pointer; color: var(--link); }
.away-list { margin: 0.4rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.25rem; }

/* ------------------------------------------- what the review asked for -- */
/* Kept together: small rules from the agents' review of 2026-10-07, each
   with the finding it answers. */

/* K14: a row a link jumps to stops below the sticky bars, not under them. */
.finder .servers tbody tr { scroll-margin-top: calc(var(--header-h) + var(--tablo-h, 3rem) + 3.5rem); }
/* K75: an empty line of conditions takes no room, at any width. */
.tablo-chips:empty { display: none; }
/* K73: the budget's head wraps where the exact-sum field does not fit. */
.meter-max .meter-head { flex-wrap: wrap; row-gap: 0.25rem; }
.finder .sort-select { border-color: var(--border-strong); }
/* K147: the price dial keeps its size where the card is as wide as the page. */
.dial { max-width: 21rem; }

/* K76, K80: without a script the finder stands above the table, whole: the
   rail's own scroll box and the bar's sticking are the script's layout. */
html:not(.js) .finder[data-layout="rail"] .console-slot { position: static; max-height: none; overflow: visible; }
html:not(.js) .tablo { position: static; }
html:not(.js) .finder .servers thead th, html:not(.js) .finder .servers tr.line-row { top: var(--header-h); }

@media not all and (min-width: 62rem) {
    /* K44, K141: a step is a button of its own here, with all four corners. */
    .step:first-child, .step:last-child { border-radius: var(--r-md); }
    /* K141: without a script the form is inside the page's own gutter. */
    html:not(.js) .console { padding-inline: 0; }
    /* K81: a focus ring is not cut by the rows that scroll sideways. */
    .finder .tabs, .tablo-chips { padding-block: 4px; margin-block: -4px; }
    /* K81: the bar fixed at the bottom covers nothing: the page ends above it. */
    body:has(.phone-bar:not([hidden])), body:has(.buy-bar:not([hidden])) { padding-bottom: calc(4.25rem + env(safe-area-inset-bottom)); }
    /* K143: "changes drives" has room under a step on the narrowest phone. */
    .build-step .step-count { white-space: normal; text-align: center; }
    /* K84: a ready configuration says when it is delivered. */
    .drive-cap.drive-lead { display: block; grid-column: 2 / -1; grid-row: 2; margin-top: 0.1rem; text-align: left; }
    /* K147: the dial is centred where the card is as wide as the page */
    .dial { margin-inline: auto; }
    /* a step whose note wraps grows with it */
    .build-step { height: auto; min-height: 4rem; }
}

/* K139: in a window too low for them — a phone on its side — the bars scroll
   with the page instead of holding half of it. */
@media (max-height: 30rem) {
    .tablo, .finder .servers thead th, .finder .servers tr.line-row { position: static; }
    .finder[data-layout="rail"] .console-slot { position: static; max-height: none; overflow: visible; }
}

/* K72: with the system's own colours forced, what is chosen is outlined. */
@media (forced-colors: active) {
    .step.is-on, .chipbox.is-on, .drive.is-on, .quick-btn[aria-pressed="true"], .avail-cell.is-on { outline: 2px solid Highlight; outline-offset: -2px; }
    .quick-btn:focus-visible, .step:has(input:focus-visible), .chipbox:has(input:focus-visible), .drive:has(input:focus-visible) { outline: 3px solid CanvasText; outline-offset: 2px; }
}

/* K81: on paper there are no bars to press. */
@media print {
    .phone-bar, .buy-bar, .sheet, .rail-toggle, .tablo-tool, .tablo-sort, .console-slot, .build-wait { display: none !important; }
    .tablo, .finder .servers thead th, .finder .servers tr.line-row { position: static; }
    .finder[data-layout="rail"] .finder-body { grid-template-columns: minmax(0, 1fr) !important; }
    body { padding-bottom: 0 !important; }
}
