/* The toning package's PURCHASE-EXPERIENCE styles (ADR-0025 §13, D.1 lane B): the fandeck wizard and the tint
   line chip, which the tinting extension renders behind the base's seam. Served from THIS package's wwwroot
   (the host's composite web root) and linked by the base's layout because the extension's IPurchaseExperience
   names it — the base ships no vendor's styles and names no file. Moved here verbatim from the base's
   storefront.css; the dialog frame (.pc-lightbox-dialog.has-configurator) and the generic chip wrapper
   (.od-variant*) stayed in the base, because every configurator uses them. */

/* §7 package ORDER ROWS in the configurator: balení báze | ks | kg/ks | celkem kg | cena. */
/* ONE GRID for the head and every row (client, 2026-09-17): each row used to be a grid of its own, so its
   `auto` tracks were measured against its own contents — the headings sat over nothing in particular and
   „8 kg" and „16 kg" stood in different places. The columns are declared here, once, and each row is a
   subgrid of them; the head keeps a transparent border so its content box is the rows' content box.
   SYMMETRICALLY (client, 2026-09-17, second pass): the four columns are EQUAL fractions of the row, so the
   data is spread evenly across its whole width instead of huddling on the left with the price pushed out
   to the right. Each cell then reads under its own heading: balení left, počet ks and celkem kg centred in
   their tracks, cena right at the row's edge.
   FIVE EQUAL COLUMNS (client, 21 October 2026): „kg/ks" — one tinted unit — joins between „Počet ks" and „Celkem kg".
   Every NUMBER (kg/ks, celkem kg, cena) is right-aligned under a right-aligned heading in tabular figures, so the
   decimal places stand in one place from row to row; the label reads left and the count control sits centred. */
.tw-rows {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    row-gap: 6px;
    column-gap: 12px;
    margin-top: 10px;
}
.tw-row {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));   /* fallback: no subgrid, still one grid */
    grid-template-columns: subgrid;
    gap: 12px;
    align-items: center;
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: color-mix(in srgb, var(--panel) 80%, transparent);
}
.tw-row-head {
    border-color: transparent;
    background: none;
    padding: 2px 12px;
    color: var(--muted);
    font-size: .8rem;
}
/* each heading over what it counts: the count is centred, the three numbers are right-aligned */
.tw-row-head span:nth-child(2) { text-align: center; }
.tw-row-head span:nth-child(n+3) { text-align: right; }
.tw-row-size { font-weight: 600; }
/* A two-component product's two tables (PD-70): „Včetně tužidla" over the tins with their hardener, „Bez tužidla" over the tins
   alone. The title reads like the rows' own heading, a step stronger; under the size, the hardener the row includes. */
.tw-rows-title { margin: 16px 0 0; font-size: .95rem; font-weight: 700; }
.tw-rows-title + .tw-rows { margin-top: 4px; }
.tw-row-hardener { display: block; font-weight: 400; font-size: .78rem; color: var(--muted); }
.tw-qty { display: flex; align-items: center; justify-content: center; gap: 4px; }
.tw-qty input {
    width: 56px;
    text-align: center;
    padding: 5px 4px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    color: var(--ink);
    font: inherit;
}
.tw-step {
    width: 28px; height: 28px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    color: var(--ink);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}
.tw-step:disabled { opacity: .4; cursor: default; }
/* The SUM on the right — the filled tin, báze + tónování — reads as loudly as the balení on the left
   (client, 2026-09-17): same size, same weight, not a muted aside. */
.tw-row-unit,
.tw-row-kg { color: var(--ink); font-weight: 600; white-space: nowrap; text-align: right; }
.tw-row-unit.muted,
.tw-row-kg.muted { color: var(--muted); font-weight: 400; }
.tw-row-price { text-align: right; white-space: nowrap; font-weight: 600; }
.tw-row-unit,
.tw-row-kg,
.tw-row-price { font-variant-numeric: tabular-nums; }
.tw-row-price small { display: block; font-weight: 400; color: var(--muted); white-space: normal; }   /* the note wraps in its column; the amount stays on one line (7 Nov 2026: „bez DPH · orientačně · informativní cena" ran past the row) */
/* ONE save, under the rows (Frank, 2026-09-05). The per-row cart glyph is gone: the rows ARE the
   order's content for this shade, and this writes them as they stand. The old .tw-row-add rule went
   with it — the row grid above dropped to four columns to match (five since „kg/ks", 21 October 2026). */
.tw-save {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 14px;
}
.tw-save-note { color: var(--muted); }
.tw-save-btn { padding: 9px 20px; font-weight: 600; }
.tw-save-btn:disabled { opacity: .5; cursor: default; }

/* §6 shade grid with visible codes under every swatch. */
.tc-grid-labeled { gap: 8px; }
.tc-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 3px;
    border: 2px solid transparent;
    border-radius: 10px;
    background: none;
    cursor: pointer;
}
.tc-cell.selected { border-color: var(--accent, var(--ochre)); }
.tc-cell .tc-swatch { width: 100%; aspect-ratio: 1.6; border-radius: 7px; display: block; }
/* The WHOLE name of the shade, its number included, stands under its swatch (client, 2026-09-17): it
   WRAPS onto as many lines as it needs and is never clipped and never ellipsised. The one-line rule this
   replaces turned a RAL deck into a grid of „RAL …". */
.tc-code {
    font-size: .68rem;
    color: var(--muted);
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.18;
    text-align: center;
}


/* ── the wizard: a horizontal track of 4 full-width slides, translated by the current page ── */
.tw { height: 100%; overflow: hidden; }
.tw-track {
    display: flex;
    width: 400%;                                   /* 4 slides */
    height: 100%;
    transform: translateX(calc(var(--tw-page) * -25%));
    transition: transform .34s var(--ease);
}
.tw-slide {
    width: 25%;                                    /* = 100% of the dialog */
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.tw-nav {
    display: flex; align-items: center; gap: 10px;
    padding: 14px 18px 8px; flex: 0 0 auto;
    border-bottom: 1px solid var(--line);
}
.tw-back {
    background: none; border: none; cursor: pointer; font: inherit;
    color: var(--accent); font-weight: 600; padding: 4px 6px; border-radius: 8px;
}
.tw-back:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.tw-nav-title { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; }
.tw-body { flex: 1 1 auto; overflow-y: auto; padding: 16px 18px; scrollbar-width: thin; min-height: 0; }
.tw-foot {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 18px; border-top: 1px solid var(--line); background: var(--card);
}

/* page A/D hero */
.tw-hero { display: flex; gap: 14px; align-items: center; margin-bottom: 12px; }
.tw-hero img { width: 96px; height: 96px; object-fit: contain; border-radius: 10px; background: var(--panel); flex: 0 0 auto; }
.tw-glyph { width: 96px; height: 96px; display: grid; place-items: center; font-size: 2.4rem; background: var(--panel); border-radius: 10px; flex: 0 0 auto; }
.tw-title { font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; line-height: 1.16; }
.tw-sub { color: var(--muted); font-size: .9rem; margin-top: 2px; }
.tw-desc { font-size: .9rem; line-height: 1.5; color: color-mix(in srgb, var(--ink) 86%, var(--muted)); max-height: 8.5em; overflow-y: auto; margin: 0 0 12px; scrollbar-width: thin; }
.tw-head { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; margin: 14px 0 8px; }

/* page A — deck chooser (wrapping) */
.tw-decks { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.tw-deck {
    display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
    padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
    background: var(--card); cursor: pointer; text-align: left; font: inherit;
    transition: border-color .15s, background .15s, transform .1s;
}
.tw-deck:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--card)); }
.tw-deck:active { transform: scale(.98); }
.tw-deck span { font-weight: 600; }
.tw-deck small { color: var(--muted); font-size: .76rem; }

/* page C — packages as full-width rows */
.tw-packages { display: flex; flex-direction: column; gap: 8px; }
.tw-pack {
    display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
    padding: 13px 15px; border: 1px solid var(--line); border-radius: 10px;
    background: var(--card); cursor: pointer; font: inherit; text-align: left;
    transition: border-color .15s, background .15s, transform .1s;
}
.tw-pack:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--card)); }
.tw-pack:active { transform: scale(.99); }
.tw-pack span { font-weight: 600; font-size: 1.02rem; }
.tw-pack small { color: var(--muted); font-size: .8rem; }

/* recap chip (pages C, D) */
.tw-recap { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.tw-recap.big { margin: 6px 0 0; }
.tw-recap > div { display: flex; flex-direction: column; line-height: 1.25; }
.tw-recap small { color: var(--muted); font-size: .8rem; }

.tw-price { font-family: var(--font-display); display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.tw-price.big { font-size: 1.05rem; }
.tw-price.big b { font-size: 1.5rem; }
.tw-price small { font-size: .78rem; color: var(--muted); font-weight: 500; }
.tw-price.muted, .tw-price.quoting { color: var(--muted); }

/* ── page B: the pickers get the whole dialog to breathe (Frank, 2026-07-24) ── */
.tw .tc-filters { flex-direction: column; align-items: stretch; gap: 12px; margin-bottom: 18px; }
.tw .tc-search { flex: none; width: 100%; font-size: 1rem; padding: 12px 14px; }
.tw .tc-family-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tw .tc-family-label { font-size: .85rem; color: var(--muted); font-weight: 600; }
.tw .tc-families { gap: 9px; flex-wrap: wrap; }
.tw .tc-family { width: 32px; height: 32px; }
.tw .tc-grid {
    grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 8px;
    max-height: min(50vh, 440px); padding: 10px; background: var(--card);
}
/* A labelled cell is as wide as its NAME needs, not as wide as its swatch: 46px fitted „RAL" and an
   ellipsis, and the name under the swatch is the point of this grid (client, 2026-09-17). */
.tw .tc-grid.tc-grid-labeled { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); }
.tw .tc-swatch { border-radius: 9px; }
.tw .tc-swatch.no-preview { min-height: 44px; font-size: .74rem; }
.tw .tc-more { margin-top: 10px; font-size: .82rem; }

/* ── page D: a proud, generous confirmation — big centred image, title, colour, price ── */
.tw-summary { display: flex; flex-direction: column; align-items: center; text-align: center; }
.tw-summary .tw-hero { flex-direction: column; gap: 14px; margin: 10px 0 20px; }
.tw-summary .tw-hero img, .tw-summary .tw-hero .tw-glyph {
    width: min(240px, 60vw); height: min(240px, 60vw); border-radius: 14px;
}
.tw-summary .tw-hero .tw-glyph { font-size: 4rem; }
.tw-summary .tw-title { font-size: 1.55rem; }
.tw-summary .tw-sub { font-size: 1rem; }
.tw-summary .tw-recap.big { justify-content: center; }
.tw-summary .tw-recap.big .tc-big-swatch { width: 66px; height: 66px; }
.tw-summary .tw-recap.big b { font-size: 1.1rem; }
/* The summary is the screen the customer commits from, so the SHADE and the MONEY must be on it without
   scrolling. Between mobile and desktop the dialog is short (it tracks viewport height) and the 240px hero
   alone pushed the recap and the price breakdown below the fold. Scale the hero to the space available
   instead — the picture is the one thing on this screen that can afford to be smaller (Frank, 2026-08-08). */
@media (max-height: 860px) {
    .tw-summary .tw-hero { margin: 4px 0 12px; gap: 10px; }
    .tw-summary .tw-hero img, .tw-summary .tw-hero .tw-glyph {
        width: min(150px, 40vw); height: min(150px, 40vw);
    }
    .tw-summary .tw-hero .tw-glyph { font-size: 3rem; }
    .tw-summary .tw-title { font-size: 1.3rem; }
    .tw-summary .tw-sub { font-size: .92rem; }
    .tw-summary .tw-recap.big .tc-big-swatch { width: 50px; height: 50px; }
}
@media (max-height: 680px) {
    .tw-summary .tw-hero img, .tw-summary .tw-hero .tw-glyph {
        width: min(104px, 30vw); height: min(104px, 30vw);
    }
    .tw-summary .tw-title { font-size: 1.15rem; }
    .tw-summary .tw-recap.big .tc-big-swatch { width: 42px; height: 42px; }
}
.tw-breakdown {
    display: flex; justify-content: center; gap: 18px; flex-wrap: wrap;
    padding: 8px 18px 0; font-size: .85rem; color: var(--muted);
}
.tw-breakdown b { color: var(--ink); font-weight: 600; }
.tw-breakdown.estimate { display: block; text-align: center; font-size: .8rem; line-height: 1.4; max-width: 40ch; margin: 0 auto; }
/* The buyer's price policy on the last screen before "Přidat natónované" — named and quantified. */
.tw-breakdown.discount { color: #2f8f4e; }
.tw-breakdown.discount b { color: #2f8f4e; }


/* Signed-out price CTAs inside the wizard: the same live „Přihlásit se pro ceny" link the base's cards use. */
.tw-price-cta, .tc-more-cta {
    border: none; background: none; padding: 0; cursor: pointer; font: inherit;
    color: var(--accent); text-decoration: underline; text-underline-offset: 3px; text-align: left;
}
.tw-price-cta:hover, .tc-more-cta:hover { color: var(--ink); }
.tw-price-cta { font-size: inherit; font-weight: 600; }
.tc-more-cta { font-size: inherit; }
.tw-pack small.muted { color: var(--muted); opacity: .75; }
/* Discount anchor on the summary: the seller's standard price, struck, so the saving has a referent. */
.tw-breakdown.anchor { color: var(--muted); }
.tw-breakdown.anchor s { color: var(--muted); }
.tw-price .tw-your { display: block; width: 100%; font-size: .72rem; font-weight: 500; color: #2f8f4e; }


/* ══ ADR-0016 — tint configurator (BAL Tónování) ═══════════════════════════════════════════════ */

.tc { display: flex; flex-direction: column; gap: 10px; padding: 12px 0 4px; border-top: 1px solid var(--line); }
.tc-head { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; }

/* fandeck strip: WRAPPING rows of card chips, capped height so a long list scrolls vertically rather
   than hiding cards off the right in a single horizontal rail (Frank, 2026-07-23). */
.tc-cards {
    display: flex; flex-wrap: wrap; gap: 6px; max-height: 108px; overflow-y: auto;
    padding: 2px 2px 4px; scrollbar-width: thin;
}
.tc-card {
    flex: 0 0 auto; border: 1px solid var(--line); border-radius: 999px; padding: 5px 12px;
    font: inherit; font-size: .82rem; cursor: pointer; white-space: nowrap;
    color: var(--ink); background: var(--card); transition: background .15s, border-color .15s;
}
.tc-card small { color: var(--muted); margin-left: 4px; }
.tc-card:hover { border-color: var(--accent); }
.tc-card.active { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.tc-card.active small { color: color-mix(in srgb, var(--accent-ink) 75%, transparent); }

/* filters: text + the colour-family dots (the closed vocabulary, shared with the agent's tags) */
.tc-filters { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.tc-search {
    flex: 1 1 150px; min-width: 130px; border: 1px solid var(--line); border-radius: 10px;
    padding: 7px 11px; font: inherit; font-size: .88rem; color: var(--ink); background: var(--card);
}
.tc-families { display: flex; gap: 5px; }
.tc-family {
    width: 22px; height: 22px; border-radius: 999px; cursor: pointer; padding: 0;
    border: 2px solid var(--line); background: var(--fam); transition: transform .12s var(--ease), border-color .15s;
}
.tc-family:hover { transform: scale(1.12); }
.tc-family.active { border-color: var(--ink); transform: scale(1.12); }
/* a family with no shades in the current card is disabled, not a dead click into "nothing matches" */
.tc-family:disabled { opacity: .28; cursor: default; filter: grayscale(.5); }
.tc-family:disabled:hover { transform: none; }

/* the swatch grid — hue-sorted, reads like a fan deck */
.tc-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(26px, 1fr)); gap: 4px;
    max-height: 190px; overflow-y: auto; padding: 2px; border: 1px solid var(--line);
    border-radius: 10px; background: var(--panel); scrollbar-width: thin;
}
.tc-swatch {
    aspect-ratio: 1; border-radius: 6px; border: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
    cursor: pointer; padding: 0; transition: transform .1s var(--ease);
}
.tc-swatch:hover { transform: scale(1.18); z-index: 1; }
.tc-swatch.selected { outline: 3px solid var(--accent); outline-offset: 1px; transform: scale(1.12); }
/* a no-preview shade (Telurmix rgb(0,0,0) sentinel), reachable by code search: a neutral labelled chip,
   never a black square. Wider so the short code reads; auto-flows in the grid. */
.tc-swatch.no-preview {
    grid-column: span 3; aspect-ratio: auto; min-height: 26px; background: var(--panel);
    border-style: dashed; color: var(--muted); font-size: .64rem; font-weight: 600;
    display: grid; place-items: center; overflow: hidden; padding: 0 2px;
}
.tc-swatch.no-preview:hover { transform: none; }
.tc-big-swatch.no-preview { background: var(--panel); border: 1px dashed var(--line); }
/* Add clicked before a package was chosen: pulse the picker and harden the hint — the guided
   alternative to a vivid-but-dead disabled button (Frank, 2026-07-24). */
.tc-packages.nudge { animation: tcNudge 0.9s ease-in-out 2; border-radius: 8px; }
.tc-price.muted.nudge { color: var(--accent); font-weight: 700; }
@keyframes tcNudge {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent); }
}
.tc-more { font-size: .78rem; color: var(--muted); margin-top: 2px; }

/* selection row: big swatch + shade identity + package pills */
.tc-selection { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.tc-big-swatch {
    width: 44px; height: 44px; border-radius: 10px; flex: 0 0 auto;
    border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); box-shadow: var(--shadow-sm);
}
.tc-sel-meta { display: flex; flex-direction: column; line-height: 1.25; min-width: 90px; }
.tc-sel-meta small { color: var(--muted); font-size: .78rem; }
.tc-packages { display: flex; gap: 6px; flex-wrap: wrap; }
.tc-pack {
    border: 1px solid var(--line); border-radius: 10px; padding: 6px 11px; font: inherit;
    font-size: .84rem; cursor: pointer; color: var(--ink); background: var(--card);
    transition: background .15s, border-color .15s;
}
.tc-pack:hover { border-color: var(--accent); }
.tc-pack.active { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* price + add — a STICKY footer of the scrolling details panel, so the price and CTA are ALWAYS on
   screen no matter how tall the fandeck/grid pushes the panel (Frank, 2026-07-23: price pushed off
   the bottom). Backed by the panel colour so swatches don't show through as it sticks. */
.tc-actions {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    position: sticky; bottom: 0; z-index: 2;
    padding: 10px 0 2px; margin-top: 2px;
    background: linear-gradient(to top, var(--card) 74%, transparent);
}
.tc-price { font-family: var(--font-display); font-weight: 600; font-size: 1.35rem; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.tc-price small { font-size: .78rem; color: var(--muted); font-family: inherit; font-weight: 500; }
.tc-price.muted, .tc-price.quoting { color: var(--muted); font-size: 1rem; }
.tc-estimate {
    font-style: normal; font-size: .72rem; font-weight: 700; letter-spacing: .02em;
    color: var(--ochre); border: 1px solid currentColor; border-radius: 999px; padding: 2px 8px;
}

/* ── ONE cart pictogram on the shelf (client, 2026-09-17) ─────────────────────────────────────────
   A tinted line's card wears the base's „configured to order" glyph (.pc-add.pc-basket, the base's
   storefront.css) — a WICKER BASKET, while every other place a customer adds something shows a shopping
   cart. The glyph is the base's markup and a tenant may not edit the base, so this package restates it:
   this sheet is linked AFTER the base's, so the cart wins. */
.pc-add.pc-basket { font-size: 0; }
.pc-add.pc-basket::before { content: "🛒"; font-size: 1.05rem; line-height: 1; }

/* the tint LINE CHIP (this extension's slot): card + shade, then the size */
.tint-chip-shade { font-weight: 600; color: var(--ink); }
.tint-chip-size { color: var(--muted); }

/* ── THE PHONE (26 Sep 2026 — the owner tests on his phone): the wizard held in one hand ─────────────────────────────
   The dialog's ✕ stands over the right end of every page's head, so the head stops short of it (the page titles ran
   under it). A balení row is a card: its size and its price, its weights, then the count — a thumb's-size stepper
   (a two-line card until „kg/ks" joined, 21 October 2026); in four equal columns the stepper overflowed its quarter of a phone and the − and + were 28px. The
   one save spans the width. Fields at 16px, so the page never zooms when one takes focus. */
@media (max-width: 760px) {
    .tw-nav { padding: 12px 60px 8px 12px; gap: 6px; }
    .tw-back { min-height: 40px; padding: 4px 8px; }
    .tw-nav-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .tw-body { padding: 12px 14px; }
    .tw-hero { padding-right: 44px; }
    .tw-deck { min-height: 52px; }
    .tw .tc-search { font-size: 16px; }
    .tw .tc-family { width: 36px; height: 36px; }
    /* Two EQUAL halves (21 October 2026): the unit's facts on the left (balení báze, kg/ks), the row's totals on
       the right (cena, celkem kg), the stepper across the card under them. The head is hidden here, so each weight
       carries its own caption from data-label. */
    .tw-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tw-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-template-areas: "size price" "unit kg" "qty qty";
        row-gap: 10px;
        padding: 10px 12px;
    }
    .tw-row-head { display: none; }
    .tw-row-size { grid-area: size; }
    .tw-row-price { grid-area: price; }
    .tw-qty { grid-area: qty; justify-content: center; }
    .tw-row-unit { grid-area: unit; align-self: center; text-align: left; }
    .tw-row-kg { grid-area: kg; align-self: center; text-align: right; }
    .tw-row-unit::before,
    .tw-row-kg::before { content: attr(data-label) " "; color: var(--muted); font-weight: 400; }
    .tw-step { width: 44px; height: 44px; font-size: 1.25rem; border-radius: 10px; }
    .tw-qty input { width: 64px; height: 44px; font-size: 16px; }
    .tw-save { flex-wrap: wrap; }
    .tw-save-btn { flex: 1 1 100%; min-height: 48px; }
    .tw-save-note { flex: 1 1 100%; text-align: center; }
}

/* ── THE FOOT'S TYPE GOES BACK TO THE BASE'S (client, 2026-09-30, fifth pass) ────────────────────────
   The enlargement is REVERTED. Tasks 78 / 81 / 87 had dressed all three .shop-foot-link buttons in
   var(--font-display) at 1.3125rem / 700 in #000, with `white-space: nowrap` and a min() floor to keep
   the two long labels unbroken and on one row. The client has now asked for „Obchodní podmínky" and
   „Ochrana osobních údajů" to read as the SMALL PRINT they were, so the whole treatment goes: family,
   size, weight, the black pin on rest and hover, and with them the nowrap and the min() — those two
   existed ONLY to make 1.3125rem fit (task 87's own note says so), and at the base's .8rem the foot's
   `flex-wrap: wrap` row needs neither. The ≤760px rung was already gone in task 87.
   WHAT THE TWO LINKS WEAR NOW is the base's own rule and nothing of ours: `font: inherit` over
   .shop-foot's .8rem, colour var(--muted), var(--ink) with an underline on :hover/:focus-visible.
   THE THIRD LINK, „Kontakty", IS NOT IN THE FOOT ANY MORE — see the block after the next one. */

/* ── …EXCEPT THE ESPRESSO THEME'S READABILITY (task 79, kept) ────────────────────────────────────────
   Task 79's fix stands, and the client asked for it to stand. The foot carries no background of its
   own, so it sits on .shop's, which under [data-theme="dark"] is --bg #18120e (the bal skin overrides
   only the accent family and the LIGHT theme — never the dark theme's bg/ink).
   WHAT THE REVERT CHANGES ABOUT IT, STATED HONESTLY: task 79 was rescuing #000 (1.13:1 there), and the
   black is gone, so the base's own resting colour is back — var(--muted) #b6a48d, which measures
   7.8:1 on that flat panel and already clears AA. This rule is therefore no longer a RESCUE; it is
   kept because it was asked to be kept, and what it now does is lift the two links from the theme's
   quiet grey to its full foreground, var(--ink) #f3e7d4 (15:1 on the flat panel), at rest and on hover.
   A TOKEN AND NOT A HAND-PICKED COLOUR, so a later retune of the theme carries the foot with it; it is
   also exactly what the base does for the foot link on :hover, and one screen up for `.btn.ghost`.
   ONE SELECTOR IS THE WHOLE OF IT: the base has four themes (ThemeKind — Light / Dark / Contrast /
   Elder) and only Dark is dark; the other three keep the base's own muted/ink behaviour untouched.
   At (0,3,0) it outranks the base's `.shop-foot-link:hover` (0,2,0), so it holds at rest and on hover;
   it does NOT reach the relocated „Kontakty" pill below, whose selector is (0,5,0). */
.shop[data-theme="dark"] .shop-foot-link { color: var(--ink); }

/* ── „KONTAKTY" MOVES OUT OF THE FOOT AND INTO THE TOP BAR, AS A BLUE BUTTON (client, 2026-09-30) ────
   THE TOP BAR IS THE BASE'S, AND THIS PACKAGE CANNOT PUT MARKUP IN IT. ShopView draws the header
   itself — the logo, .page-head, the actions cluster (Vzhled · the sign-in card · the basket · the
   burger) and the burger's dropdown — and the tenant tier offers no slot there: IPurchaseExperience
   contributes exactly three COMPONENTS (Configurator, LineChip, ShelfBadge) plus a list of
   Stylesheets, and tenant.json carries no chrome entry for a header action. Nothing we can write
   renders inside .topbar.
   WHAT WE CAN DO: THE BUTTON ALREADY EXISTS. The foot's first .shop-foot-link IS „Kontakty" — the very
   control that opens the document page, carrying the base's own click handler. This block draws no new
   button: it MOVES that one into the header row and dresses it as a top-bar pill. There is still
   exactly one Kontakty control on the page and it still opens the page it always opened.
   WHICH ONE IT IS. The foot is `<footer class="shop-foot">` with exactly three
   `<button class="shop-foot-link">` children — Kontakty, Obchodní podmínky, Ochrana osobních údajů, in
   that order and unconditionally (read off the base's own render code at 2026.9.28.2, no branch
   between them) — so `> :first-child` is Kontakty and can be nothing else. That is an ORDER inside one
   fixed row, not a census of the page: the trap tasks 86 and 88 recorded is a count that another page
   can also satisfy, and there is only one shop foot.
   THE SLOT IS RESERVED, NOT OVERLAID, AND IT IS RESERVED ON THE HEADER ROW ITSELF (the client, 1 October
   2026: „Přihlášení" and „Kontakty" photographed one on top of the other). .topbar takes a padding-right
   of the pill's width plus 12px, so EVERY control in the row — TradeSignInCard's „👤 Přihlášení" button
   or the buyer chip it becomes once signed in, ◐ Vzhled, the basket — ends at least 12px to the pill's
   left and nothing can overlap at any width. Both declarations read ONE variable for that width, so the
   reservation cannot drift from the thing it reserves.
   WHY THE ROW, AND NOT THE SIGN-IN'S OWN WRAPPER — which is what this block reserved on when it was
   written, and the reason the pill painted over „Přihlášení" from its first day: the margin was hung on
   .topbar-desk-actions, and THAT CLASS IS NOT ON THE STOREFRONT. It is the BACK OFFICE's wrapper — the
   base draws `<div class="topbar-wide topbar-desk-actions">` around ShopView.DeskActions, the
   host-supplied „Odhlásit" of the desk — and the shop passes no DeskActions, so the shop's sign-in is a
   bare `.topbar-wide > div > button.btn.topbar-action.user-signin` and the rule matched NOTHING there.
   .topbar is the row itself and the shop has it on every view; reserving there also covers the controls
   that are SIBLINGS of .topbar-actions rather than inside it (◐ Vzhled, the basket, the burger), which
   a wrapper's margin could never have covered — in the client's photograph the ◐ was buried whole.
   WHERE IT LANDS. Out of flow with `position: fixed`, measured from the window's top-right corner: the
   window is the shop grid's second track and runs flush to the viewport's top and right edge, and its
   own padding is var(--gap) — so `top: var(--gap)` IS the header row's top edge and `right: var(--gap)`
   its right edge. THE PILL AND THE ROW THEREFORE MEASURE FROM ONE ORIGIN: .topbar's right edge is that
   same var(--gap) from the viewport, so the padding above clears exactly the pill plus 12px of air at
   every width, and the one variable keeps the two in step. ONE OFFSET, BASKET OR NO BASKET: with the
   room taken off the row the basket stays in flow to the pill's left, so there is nothing to step past
   and no hole to leave when the tray button is absent. (The burger is `display: none` above 980px on
   the storefront.)
   VERTICAL. .topbar is `align-items: center` and its height is whatever .page-head makes it (a crumb
   trail plus a 1.6rem title ≈ 53px; 40px on a view with no head), which a fixed element cannot read.
   So the header's own items are pinned to the TOP of the row instead — one declaration on .topbar —
   and the pill, 40px tall like the theme buttons beside it, sits at that same edge. On a page with a
   crumb trail the controls rise ~6px and the logo ~4px; nothing else in the header moves.
   Z-ORDER. .topbar is z 300 and, having a box of its own, would hit-test over a pill painted under it,
   so the foot's stacking context goes to 301 while the pill lives in it — still below the basket tray
   (400/401) and every dialog (1000), and the foot overlaps nothing at the bottom of the window.
   BETWEEN THE SIGN-IN AND ◐ VZHLED, NOT AT THE ROW'S END (the client's order, 30 September 2026:
   [Nainstalovat aplikaci] · Přihlášení · Kontakty · ◐ Vzhled, the basket beside the ◐). Everything
   above is the FALLBACK, and it puts the pill at the far right, past the ◐. Where the browser has
   CSS anchor positioning the room moves INTO THE ROW'S OWN FLOW instead: ◐ Vzhled (.topbar-appearance,
   which the base draws straight after .topbar-actions and before the basket, on every storefront
   view) takes a margin-left of the pill's width plus one row gap, the row's padding goes back to the
   base's none, and the pill is anchored to that ◐ — its top on the ◐'s top, its right edge one row gap
   short of the ◐'s left edge. So the hole sits wherever the row's flow puts the ◐, and the pill sits in
   the hole: the sign-in (and the install pill before it) stand to its left, the ◐ and the basket to its
   right, and NO OFFSET TRACKS ANY OTHER CONTROL'S WIDTH — a longer buyer chip or a missing install
   pill moves the ◐, and the pill moves with it. The only width in play is the pill's own, read off the
   same variable as before. Because the pill reads the ◐'s own top, the row's items go back to the
   base's centring. THE ROW FILLS FROM ITS RIGHT (row-reverse with wrap-reverse; `order` puts the logo
   back at the left and the actions · ◐ · the buttons after it — the basket — back in reading order, the
   page's head keeping the default between them), so the controls are laid down first and stay
   together on one line; when the crumb trail and title cannot share that line they take the line above
   it, as the base's own wrap already did, instead of the controls splitting across two lines. A browser
   without anchor positioning keeps the end-of-row placement whole, so it never gets a hole with no
   pill in it.
   DESKTOP, AND THE STOREFRONT ONLY. Below 981px the base hides .topbar-actions outright and folds the
   header into the burger, whose FIRST entry is „✉ Kontakty" — the same page, already in the top bar,
   put there by the platform. So there the pill has nowhere to sit and the foot link is simply hidden,
   which is also what „no longer in the footer" asks for. `.shop:not(.desk)` keeps every line of this
   off the back office, whose header row is a different one.
   THE BURGER KEEPS THE SAME ORDER. Its column runs Kontakty · Obchodní podmínky · Ochrana osobních
   údajů · Vzhled… · Nainstalovat aplikaci · and last the account (.menu-account, which holds the sign-in
   or the buyer chip). The column is a flex box, so `order` lifts the install item ([data-install-app])
   and then the account to its head — Nainstalovat aplikaci · Přihlášení · Kontakty · … · Vzhled…, the
   desktop row's order — and the account's divider moves from above it to below it.
   THE BLUE is var(--accent) — #0a6cb5 under data-brand="bal", the BAL blue — which is exactly what the
   „👤 Přihlášení" button beside it already wears (it is a .btn, and .btn is `background: var(--accent)`).
   The pill copies .btn and `.topbar-actions .btn.topbar-action`: 999px radius, weight 600, .95rem,
   16px of side padding, var(--accent-press) on hover, the press nudge, and the contrast theme's 2px
   black border with no shadow. */
.shop { --kt-top-pill: 7rem; }          /* the pill's width — read by the pill AND by the slot it reserves */
.shop:not(.desk) .shop-foot > .shop-foot-link:first-child { display: none; }

@media (min-width: 981px) {
    .shop:not(.desk) .shop-foot { z-index: 301; }
    /* the row keeps the pill's room clear — see „THE SLOT IS RESERVED" above */
    .shop:not(.desk) .topbar { align-items: flex-start; padding-right: calc(var(--kt-top-pill) + 12px); }
    .shop:not(.desk) .shop-foot > .shop-foot-link:first-child {
        position: fixed;
        top: var(--gap);
        right: var(--gap);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: var(--kt-top-pill);
        height: 40px;
        padding: 0 16px;
        border: none;
        border-radius: 999px;
        background: var(--accent);
        color: var(--accent-ink);
        font: inherit;
        font-size: .95rem;
        font-weight: 600;
        white-space: nowrap;
        text-decoration: none;
        box-shadow: var(--shadow-sm);
        cursor: pointer;
        transition: transform .12s var(--ease), background .2s, box-shadow .2s;
    }
    .shop:not(.desk) .shop-foot > .shop-foot-link:first-child:hover,
    .shop:not(.desk) .shop-foot > .shop-foot-link:first-child:focus-visible {
        background: var(--accent-press);
        color: var(--accent-ink);
        text-decoration: none;
    }
    .shop:not(.desk) .shop-foot > .shop-foot-link:first-child:active { transform: translateY(1px) scale(.99); }
    .shop[data-theme="contrast"]:not(.desk) .shop-foot > .shop-foot-link:first-child {
        border: 2px solid #000;
        box-shadow: none;
    }
    /* the pill between the sign-in and ◐ Vzhled — see „BETWEEN THE SIGN-IN AND ◐ VZHLED" above */
    @supports (anchor-name: --kt-vzhled) {
        .shop:not(.desk) .topbar {
            padding-right: 0;
            flex-direction: row-reverse;
            flex-wrap: wrap-reverse;
            align-items: center;
        }
        .shop:not(.desk) .topbar > .topbar-logo { order: 1; margin-right: auto; }
        .shop:not(.desk) .topbar > .topbar-actions { order: -1; }
        .shop:not(.desk) .topbar-appearance {
            order: -2;
            anchor-name: --kt-vzhled;
            margin-left: calc(var(--kt-top-pill) + var(--gap));
        }
        .shop:not(.desk) .topbar-appearance ~ .theme-btn { order: -3; }
        .shop:not(.desk) .shop-foot > .shop-foot-link:first-child {
            position-anchor: --kt-vzhled;
            top: anchor(top);
            right: calc(anchor(left) + var(--gap));
        }
    }
}
.shop:not(.desk) .topbar-menu > [data-install-app] { order: -2; }
.shop:not(.desk) .topbar-menu > .menu-account {
    order: -1;
    border-top: none;
    margin-top: 0;
    padding-top: 0;
    border-bottom: 1px solid var(--line);
    margin-bottom: 6px;
    padding-bottom: 10px;
}

/* ── „KONTAKTY" AS THE CLIENT'S CONTACT SHEET (client, 2026-09-30: „Zpracuj dle předloženého designu") ──
   Task 82 put the sample's CONTENT on this page, task 83 its DESIGN — the header band, the multi-column
   company details, the grey group bars, and the people as CARDS in a grid. The client then asked for the
   sample AND NOTHING BESIDE IT („striktně dle předlohy"), so on the third pass everything the earlier two
   had kept or invented beyond the image came off the page: the „Výrobce nátěrových hmot…" strapline, the
   BAL group infoline, the „Web:" line, the registration date, the „Obchod a objednávky" lead sentence,
   the „Reklamace a odstoupení od smlouvy" section, the demo disclaimer, and the heading task 82 had put
   over the sample's unlabelled final block. THE INDEX MAP BELOW MOVED WITH THEM — see the re-count.

   WHAT THE BASE RENDERS (ShopView.razor, the note panel): doc.Text is split on a blank line; a section
   of more than one line becomes <h3>first line</h3> plus one <p> per remaining line, a one-line section
   becomes a lone <p>. Every line goes through AddContent, so it is ESCAPED TEXT — an <img>, a <span> or
   a class typed into tenant.json would be shown as literal characters. What we get is a FLAT run of
   <h3>/<p> inside .doc-page-body: no wrappers, no attributes, nothing to hang a card on but position.

   SO THE NOTE CARRIES THE STRUCTURE AND THIS SHEET CARRIES THE LOOK. tenant.json's ContactsNote is
   written in the shape this design needs:
     · section 1    — the company name ALONE, so it arrives as a lone <p> (the sample sets nothing
                      under it, and a one-line section cannot be an <h3>)
     · sections 2-5 — the header band's four labelled groups: a label (h3) and its lines (p). They
                      READ as THREE blocks (client, 2026-10-01): „Expediční sklad" is stacked under
                      „Sídlo společnosti" inside the first of them, which is a placement and not a
                      section — the note still carries four labels, and so four <h3>.
     · section 6    — „Obchod a objednávky", also alone now, so also a lone <p>
     · a group bar  — its own ONE-LINE section, so it arrives as a lone <p>
     · a person     — its own section: NAME (h3), function (p), telephone (p), e-mail (p)
   which the base turns into exactly 28 <h3> and 89 <p>. The index map below IS that DOM, counted, and it
   is re-derivable in one line (split ContactsNote on a blank line; the first line of a multi-line section
   is an h3, every other line a p). IT MUST BE RE-COUNTED IF THE NOTE'S LINES EVER MOVE.
     p1        the company lockup            h3 1-4 / p2-p10   the header band's three blocks
     p11       „Obchod a objednávky"         p12,22,38,49,55,65 the six group bars
     p48       the shared-address bar        h3 5-28 / the rest the twenty-four person cards
   RE-COUNTED ON 2026-10-01, when each of the two addresses became ONE line („č.p. 1, 679 61 Skrchov",
   „č.p. 57, 679 61 Skrchov") where it had been two: that is two <p> fewer in the band, so every index
   from the old p13 down moved down two (old p91 is new p89) and no <h3> moved at all.
   THE SAMPLE'S FINAL BLOCK CARRIES NO BAR and needs none: a bar is a section of its own, so leaving it
   out is leaving a section out. What the block does need is the break the bar used to give it, and that
   is the rule on h3:nth-of-type(23) (and, once the cards are in a row, on 24 and 25).

   SCOPING IS THE CONTAINER, NOT A :has() REPEATED ON EVERY RULE. One guarded rule makes THIS doc page a
   NAMED query container; everything else sits inside @container kontakty(…), which cannot match an
   element with no such container above it. The other two pages are therefore untouched by construction
   rather than by discipline, and a browser too old for container queries simply gets the base's plain
   note. The task-77 terms picture is unaffected: its guard wants FEWER than twenty paragraphs, and this
   page has 89.

   WHAT THE GUARD ASKS IS THE NOTE'S WHOLE FINGERPRINT, NOT A THRESHOLD. There is NOTHING in the base's
   markup at 2026.9.28.2 that names the open document: ShopView writes `class="doc-page"` and a @key,
   and a @key is not an attribute — the only place the title appears is as TEXT in .doc-page-head h2 and
   in the cross-link strip's button labels, and CSS cannot read text. So a count is the only handle there
   is, and the honest thing to do with it is to make it EXACT rather than a floor: 28 <h3> and 89 <p>,
   no more and no fewer. A floor („twenty headings", which was the earlier guard) is the shape task 86
   recorded leaking between these three pages — „Obchodní podmínky" is a legal text that grows, and the
   day it reaches a twentieth heading it would have inherited this entire sheet. The exact pin cannot:
   a page must be THIS note to match. It also fails SAFE in the other direction — the index map below is
   already pinned element by element up to p89, so a note whose lines move has broken the sheet whatever
   the guard says; with the pin it falls back to the base's plain note instead of drawing a garbled one.
   (Today's other two notes are 11 <h3> / 12 <p> and 6 <h3> / 7 <p>, so neither is anywhere near.)

   THE COLUMNS ARE A 12-TRACK GRID over the flat run, packed `dense` so that a card's four elements stack
   DOWN one column instead of running across the row. Dense packing back-fills holes, so there are no
   holes to back-fill: a group of two (and the odd fifth of a group of five) takes two SIX-track halves
   rather than leaving a third slot empty, and the one person who has no e-mail address in this package
   (Václav Kubíček) has his telephone line span the row his e-mail would have filled. The band is kept
   square the same way — its three blocks are 4/4/5 items deep, so the short ones span. That is this
   sheet's one deliberate departure from the image, which leaves such slots blank.

   THE PALETTE IS THE TENANT'S, NOT THE IMAGE'S: the sample's blue is var(--accent), which under
   data-brand="bal" IS BAL blue (#0a6cb5), and the bands are color-mix() over var(--panel)/var(--ink).
   So the sheet stays legible on all four themes (light/dark/contrast/elder), not only on white. */

.doc-page:has(> .doc-page-body > h3:nth-of-type(28)):not(:has(> .doc-page-body > h3:nth-of-type(29))):has(> .doc-page-body > p:nth-of-type(89)):not(:has(> .doc-page-body > p:nth-of-type(90))) {
    container: kontakty / inline-size;
}

@container kontakty (min-width: 0px) {
    /* ── THE OTHER TWO DOCUMENTS' TITLES ARE NOT PART OF THIS SHEET (client, 2026-09-30) ─────────────
       ShopView renders the cross-links to the other notes INSIDE .doc-page-body, not after it: the
       `<div class="note-links doc-page-links">` goes up while the body element is still open and only
       the body's own CloseElement follows it. So on this page they are not a footer at all — they are
       a GRID ITEM of the twelve-track sheet below, with no grid-column of their own. The run is
       hole-free by design (see above), so `dense` has nothing to back-fill and drops the strip on a row
       of its own as ONE track of twelve: „Obchodní podmínky" and „Ochrana osobních údajů" wrapped into
       a sliver a twelfth of the page wide, under a hairline the same stub width, directly beneath the
       last person card — a twenty-fifth card in all but name. That is the „Obchodní podmínky a Ochrana
       osobních údajů jsou pořád součástí stránky Kontakty" the client is reporting, and it is ours: the
       strip read as the base's plain footer until task 83 made the body a grid.
       THEY ARE HIDDEN, NOT LAID OUT FLAT, BECAUSE THE SAME THREE LINKS NEVER LEAVE THE SCREEN. The foot
       is a sibling of .gallery, not of the document, so .shop-foot — „Kontakty · Obchodní podmínky ·
       Ochrana osobních údajů", the very links tasks 79/81/85 enlarged — stays visible under the open
       page. This strip only ever repeated the row beneath it, so nothing is lost with it and no reader
       is stranded: the sheet ends on a contact card and the way out is where it always was.
       THIS PAGE ONLY. The rule lives in the container, which no other note opens, so „Obchodní
       podmínky" and „Ochrana osobních údajů" keep the base's strip exactly as the base ships it. */
    .doc-page-body > .note-links { display: none; }

    /* the base caps a note at 72ch of prose; a contact sheet is a layout, not a column of text */
    .doc-page-body { max-width: none; }
    .doc-page-body > h3,
    .doc-page-body > p { margin: 0; overflow-wrap: break-word; }

    /* ── the page's own lockup: a lone <p>, the sample setting no second line under the name ── */
    .doc-page-body > p:nth-of-type(1) {
        font-size: 1.85rem;
        font-weight: 800;
        letter-spacing: -.01em;
        line-height: 1.15;
        padding: 0 0 1rem;
    }

    /* ── THE HEADER BAND IS THREE BLOCKS NOW, AND WEARS NO PICTOGRAMS (client, 2026-10-01) ──────────
       Four things were asked for here and three of them are one thing. The client reads the band as
       „Sídlo společnosti" (with the dispatch warehouse UNDER it, not beside it), „Kontakt" and „Firemní
       údaje" — THREE blocks, laid out the way the blocks under „Obchod a objednávky" already are, which
       on this sheet means EQUAL THIRDS of the twelve-track grid, ruled apart by the same hairline, from
       the same 800px at which the cards go three to a row. So the band no longer opens out in two steps
       (two columns at 800px, four at 1040px): it is ONE column on a phone and THREE equal blocks above
       800px, and the 1040px step is gone with the fourth column it existed to deal.
       THE PICTOGRAMS GO WITH THE INDENT THEY PAID FOR. The four ::before masks hung in a 2.5rem left
       padding that nothing else on the sheet shares — the cards below pad .9rem — so every line of the
       band started 1.6rem to the right of every line under it, which is the misalignment the client is
       reporting. Dropping the icons gives that 1.6rem back TO THE TEXT, and the band and the cards now
       share one left edge. The icons that STAY are the cards' own telephone/e-mail marks and the shared
       address bar's: the request names the band, and those are not in it.
       THE ADDRESSES ARE ONE LINE EACH, so the note is TWO LINES SHORTER and every index after the band
       moved down two — the band is h3 1-4 / p2-p10 where it was h3 1-4 / p2-p12, p13 became p11, and so
       on to p91 → p89, the container guard above included. The index map at the head of this sheet is
       re-counted; nothing else about the run changed, the h3 count least of all (28 before and after:
       „Expediční sklad" is still a section of its own, and so still a heading of its own). ── */
    .doc-page-body > h3:nth-of-type(1),
    .doc-page-body > h3:nth-of-type(2),
    .doc-page-body > h3:nth-of-type(3),
    .doc-page-body > h3:nth-of-type(4),
    .doc-page-body > p:nth-of-type(2),
    .doc-page-body > p:nth-of-type(3),
    .doc-page-body > p:nth-of-type(4),
    .doc-page-body > p:nth-of-type(5),
    .doc-page-body > p:nth-of-type(6),
    .doc-page-body > p:nth-of-type(7),
    .doc-page-body > p:nth-of-type(8),
    .doc-page-body > p:nth-of-type(9),
    .doc-page-body > p:nth-of-type(10) {
        background: color-mix(in srgb, var(--accent) 7%, var(--panel));
        border-radius: 0;
    }
    .doc-page-body > h3:nth-of-type(1),
    .doc-page-body > h3:nth-of-type(2),
    .doc-page-body > h3:nth-of-type(3),
    .doc-page-body > h3:nth-of-type(4) {
        font-size: .92rem;
        font-weight: 700;
        line-height: 1.25;
        padding: .9rem .9rem .15rem;
    }
    .doc-page-body > p:nth-of-type(2),
    .doc-page-body > p:nth-of-type(3),
    .doc-page-body > p:nth-of-type(4),
    .doc-page-body > p:nth-of-type(5),
    .doc-page-body > p:nth-of-type(6),
    .doc-page-body > p:nth-of-type(7),
    .doc-page-body > p:nth-of-type(8),
    .doc-page-body > p:nth-of-type(9),
    .doc-page-body > p:nth-of-type(10) {
        font-size: .85rem;
        line-height: 1.5;
        color: var(--muted);
        padding: .05rem .9rem;
    }
    /* the panel's corners. Stacked, the band is ONE column: its first item caps the top, its last the
       foot; the width below re-points them at whatever item is then in the corner. */
    .doc-page-body > h3:nth-of-type(1) { border-start-start-radius: 10px; border-start-end-radius: 10px; }
    .doc-page-body > p:nth-of-type(10) { border-end-start-radius: 10px; border-end-end-radius: 10px; }
    /* the last line of each labelled group closes it off, stacked or in a block */
    .doc-page-body > p:nth-of-type(2),
    .doc-page-body > p:nth-of-type(3),
    .doc-page-body > p:nth-of-type(6),
    .doc-page-body > p:nth-of-type(10) { padding-bottom: .9rem; }

    /* ── THE THREE LINES THAT MUST NOT BREAK (client, 2026-10-01 and, for the e-mail, 2026-10-01's
          earlier request) ──────────────────────────────────────────────────────────────────────────
       „Každá adresa musí být na JEDNOM řádku" is a guarantee, not a rescue. Both addresses are SHORTER
       than „Objednávky: prodej@teluria.cz", which task 95 measured at 197px in the shipped Inter at
       .85rem; a third of the band is 267px at the 800px the blocks open at, which the .9rem padding
       leaves 238px of as TEXT — where the 2.5rem icon indent left 212px, so taking the pictograms off
       is what turns this from tight into comfortable. What `nowrap` buys is the day that is not true:
       a fallback face (Inter blocked, system-ui on a Linux box), a reader whose browser's default text
       size is 17px, one more character in a street number. Unlike the e-mail line, an address holds
       several spaces and would wrap at any of them, so `nowrap` is the whole of „no break inside the
       address". It reaches these three and nothing else in the band, so „Spisová značka: C 4055 u rejstříkového
       soudu v Brně" still wraps where it always did and still caps the panel's foot.
       IF ONE EVER DOES OVERRUN its block it scrolls rather than spreads: the base sets `overflow: auto`
       on .doc-page, so a line too long for the sheet cannot widen the page under it. */
    .doc-page-body > p:nth-of-type(2),
    .doc-page-body > p:nth-of-type(3),
    .doc-page-body > p:nth-of-type(5) { white-space: nowrap; }

    /* ── „Obchod a objednávky", the sheet's one section title (a lone <p> too, now that the sentence
          task 82 wrote under it — which the sample has not got — is gone) ── */
    .doc-page-body > p:nth-of-type(11) {
        font-size: 1.45rem;
        font-weight: 800;
        letter-spacing: -.01em;
        line-height: 1.2;
        padding: 1.6rem 0 .25rem;
    }

    /* ── a group bar: its own one-line section, so a lone <p> straight across the sheet ── */
    .doc-page-body > p:nth-of-type(12),
    .doc-page-body > p:nth-of-type(22),
    .doc-page-body > p:nth-of-type(38),
    .doc-page-body > p:nth-of-type(49),
    .doc-page-body > p:nth-of-type(55),
    .doc-page-body > p:nth-of-type(65) {
        background: color-mix(in srgb, var(--ink) 6%, var(--panel));
        border-radius: 8px;
        margin: 1.35rem 0 .1rem;
        padding: .5rem .85rem;
        font-size: 1.02rem;
        font-weight: 700;
        color: var(--ink);
    }

    /* ── a person card: NAME (h3) · function · telephone · e-mail ──
       The three detail lines are chosen by their DISTANCE FROM THE NAME and never by a count, so the one
       person with no e-mail address needs no exception; the lower bound (p13, the first function line) is
       what keeps the header band's own h3+p runs out of the card styling, and no upper bound is needed
       any more — the sheet now ENDS on a card, the two closing paragraphs having gone with the sample.
       THE E-MAIL LINE ALONE EXCLUDES THE GROUP BARS, because a card one line short lets `h3 + p + p + p`
       reach past it: Václav Kubíček's card ends at his telephone, which puts the „Tónování" bar (p55)
       exactly three <p> after his name — and at (0,3,4) that chain outranks the bar's own (0,2,1) rule,
       so the bar would have been drawn as an e-mail line. Every bar is listed, not just the one that
       collides today, so the same mistake cannot arrive through some other short card. */
    .doc-page-body > h3 {
        font-size: .97rem;
        font-weight: 700;
        line-height: 1.3;
        padding: .85rem .9rem .12rem;
    }
    .doc-page-body > h3 + p:nth-of-type(n+13) {
        font-size: .86rem;
        color: var(--muted);
        padding: 0 .9rem .3rem;
    }
    .doc-page-body > h3 + p + p:nth-of-type(n+13),
    .doc-page-body > h3 + p + p + p:nth-of-type(n+13):not(:nth-of-type(12), :nth-of-type(22), :nth-of-type(38),
          :nth-of-type(48), :nth-of-type(49), :nth-of-type(55), :nth-of-type(65)) {
        font-size: .86rem;
        line-height: 1.45;
        color: var(--ink);
        padding: 0 .9rem .1rem 2.3rem;
        position: relative;
    }
    .doc-page-body > h3 + p + p:nth-of-type(n+13)::before,
    .doc-page-body > h3 + p + p + p:nth-of-type(n+13):not(:nth-of-type(12), :nth-of-type(22), :nth-of-type(38),
          :nth-of-type(48), :nth-of-type(49), :nth-of-type(55), :nth-of-type(65))::before {
        content: "";
        position: absolute;
        left: .9rem;
        top: .18rem;
        width: .95rem;
        height: .95rem;
        background: var(--accent);
        -webkit-mask: var(--kt-icon) center / contain no-repeat;
        mask: var(--kt-icon) center / contain no-repeat;
    }
    .doc-page-body > h3 + p + p:nth-of-type(n+13) { --kt-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='6' y='2' width='12' height='20' rx='2'/%3E%3Cpath d='M12 18h.01'/%3E%3C/svg%3E"); }
    .doc-page-body > h3 + p + p + p:nth-of-type(n+13):not(:nth-of-type(12), :nth-of-type(22), :nth-of-type(38),
          :nth-of-type(48), :nth-of-type(49), :nth-of-type(55), :nth-of-type(65)) { --kt-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m2 7 10 6 10-6'/%3E%3C/svg%3E"); padding-bottom: .95rem; }
    /* Václav Kubíček holds no e-mail address in this package, so his telephone closes his card */
    .doc-page-body > p:nth-of-type(54) { padding-bottom: .95rem; }

    /* ── the shared address the sample prints as a tinted bar of its own ── */
    .doc-page-body > p:nth-of-type(48) {
        background: color-mix(in srgb, var(--accent) 11%, var(--panel));
        border-radius: 8px;
        margin: 1.1rem 0 .1rem;
        padding: .6rem .9rem .6rem 2.6rem;
        font-size: .95rem;
        font-weight: 600;
        position: relative;
        --kt-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m2 7 10 6 10-6'/%3E%3C/svg%3E");
    }
    .doc-page-body > p:nth-of-type(48)::before {
        content: "";
        position: absolute;
        left: 1rem;
        top: .75rem;
        width: 1.05rem;
        height: 1.05rem;
        background: var(--accent);
        -webkit-mask: var(--kt-icon) center / contain no-repeat;
        mask: var(--kt-icon) center / contain no-repeat;
    }

    /* ── the sample's final block wears no bar, so the break it would have given is drawn instead ── */
    .doc-page-body > h3:nth-of-type(23) { margin-top: 1.35rem; border-top: 1px solid var(--line); padding-top: 1.6rem; }
}

/* ── THE SHEET'S COLUMNS. Narrower than this the page is one column — every card, band column and bar
      simply stacks in reading order, which is the phone layout and needs no rule of its own. ── */
@container kontakty (min-width: 800px) {
    .doc-page-body {
        display: grid;
        grid-template-columns: repeat(12, minmax(0, 1fr));
        grid-auto-flow: row dense;
        gap: 0;
    }

    /* the full-bleed run: the lockup, the section title, the group bars, the shared address */
    .doc-page-body > p:nth-of-type(1),
    .doc-page-body > p:nth-of-type(11),
    .doc-page-body > p:nth-of-type(12),
    .doc-page-body > p:nth-of-type(22),
    .doc-page-body > p:nth-of-type(38),
    .doc-page-body > p:nth-of-type(48),
    .doc-page-body > p:nth-of-type(49),
    .doc-page-body > p:nth-of-type(55),
    .doc-page-body > p:nth-of-type(65) { grid-column: 1 / -1; }

    /* THE HEADER BAND, THREE BLOCKS ACROSS — equal thirds of the twelve, placed exactly as the card
       rows below are placed (1/5, 5/9, 9/13) and ruled off with the same hairline, which is the
       „stejný blokový styl jako u bloku Obchod" the client asked for. „Expediční sklad" is the second
       labelled group INSIDE the first block, stacked under „Sídlo společnosti" rather than standing
       beside it.
       THE BLOCKS ARE 4, 4 AND 5 ITEMS DEEP, so the two short ones end on an item that spans the fifth
       row — the same trick the band has always used to stay square. It is not cosmetic: the grid is
       packed `dense`, and an empty cell left at the band's foot is a cell the next item that fits
       back-fills, which here is the FIRST PERSON'S NAME (h3:5 is a 1/5 item too). The spans keep the
       panel a rectangle and keep Aleš Gajdošík out of it. */
    .doc-page-body > h3:nth-of-type(1),
    .doc-page-body > p:nth-of-type(2),
    .doc-page-body > h3:nth-of-type(2),
    .doc-page-body > p:nth-of-type(3) { grid-column: 1 / 5; }
    .doc-page-body > h3:nth-of-type(3),
    .doc-page-body > p:nth-of-type(4),
    .doc-page-body > p:nth-of-type(5),
    .doc-page-body > p:nth-of-type(6) { grid-column: 5 / 9; }
    .doc-page-body > h3:nth-of-type(4),
    .doc-page-body > p:nth-of-type(7),
    .doc-page-body > p:nth-of-type(8),
    .doc-page-body > p:nth-of-type(9),
    .doc-page-body > p:nth-of-type(10) { grid-column: 9 / 13; }
    .doc-page-body > p:nth-of-type(3),
    .doc-page-body > p:nth-of-type(6) { grid-row: span 2; }
    /* the hairlines, one down every block but the first — the cards' own rule, over the band */
    .doc-page-body > h3:nth-of-type(3),
    .doc-page-body > p:nth-of-type(4),
    .doc-page-body > p:nth-of-type(5),
    .doc-page-body > p:nth-of-type(6),
    .doc-page-body > h3:nth-of-type(4),
    .doc-page-body > p:nth-of-type(7),
    .doc-page-body > p:nth-of-type(8),
    .doc-page-body > p:nth-of-type(9),
    .doc-page-body > p:nth-of-type(10) { border-left: 1px solid var(--line); }
    /* the corners the three blocks now hold between them */
    .doc-page-body > h3:nth-of-type(1) { border-start-end-radius: 0; }
    .doc-page-body > h3:nth-of-type(4) { border-start-end-radius: 10px; }
    .doc-page-body > p:nth-of-type(10) { border-end-start-radius: 0; }
    .doc-page-body > p:nth-of-type(3) { border-end-start-radius: 10px; }

    /* three cards to a row … */
    .doc-page-body > h3:nth-of-type(5),
    .doc-page-body > p:nth-of-type(13),
    .doc-page-body > p:nth-of-type(14),
    .doc-page-body > p:nth-of-type(15),
    .doc-page-body > h3:nth-of-type(8),
    .doc-page-body > p:nth-of-type(23),
    .doc-page-body > p:nth-of-type(24),
    .doc-page-body > p:nth-of-type(25),
    .doc-page-body > h3:nth-of-type(13),
    .doc-page-body > p:nth-of-type(39),
    .doc-page-body > p:nth-of-type(40),
    .doc-page-body > p:nth-of-type(41),
    .doc-page-body > h3:nth-of-type(18),
    .doc-page-body > p:nth-of-type(56),
    .doc-page-body > p:nth-of-type(57),
    .doc-page-body > p:nth-of-type(58),
    .doc-page-body > h3:nth-of-type(23),
    .doc-page-body > p:nth-of-type(72),
    .doc-page-body > p:nth-of-type(73),
    .doc-page-body > p:nth-of-type(74),
    .doc-page-body > h3:nth-of-type(26),
    .doc-page-body > p:nth-of-type(81),
    .doc-page-body > p:nth-of-type(82),
    .doc-page-body > p:nth-of-type(83) { grid-column: 1 / 5; }
    .doc-page-body > h3:nth-of-type(6),
    .doc-page-body > p:nth-of-type(16),
    .doc-page-body > p:nth-of-type(17),
    .doc-page-body > p:nth-of-type(18),
    .doc-page-body > h3:nth-of-type(9),
    .doc-page-body > p:nth-of-type(26),
    .doc-page-body > p:nth-of-type(27),
    .doc-page-body > p:nth-of-type(28),
    .doc-page-body > h3:nth-of-type(14),
    .doc-page-body > p:nth-of-type(42),
    .doc-page-body > p:nth-of-type(43),
    .doc-page-body > p:nth-of-type(44),
    .doc-page-body > h3:nth-of-type(19),
    .doc-page-body > p:nth-of-type(59),
    .doc-page-body > p:nth-of-type(60),
    .doc-page-body > p:nth-of-type(61),
    .doc-page-body > h3:nth-of-type(24),
    .doc-page-body > p:nth-of-type(75),
    .doc-page-body > p:nth-of-type(76),
    .doc-page-body > p:nth-of-type(77),
    .doc-page-body > h3:nth-of-type(27),
    .doc-page-body > p:nth-of-type(84),
    .doc-page-body > p:nth-of-type(85),
    .doc-page-body > p:nth-of-type(86) { grid-column: 5 / 9; }
    .doc-page-body > h3:nth-of-type(7),
    .doc-page-body > p:nth-of-type(19),
    .doc-page-body > p:nth-of-type(20),
    .doc-page-body > p:nth-of-type(21),
    .doc-page-body > h3:nth-of-type(10),
    .doc-page-body > p:nth-of-type(29),
    .doc-page-body > p:nth-of-type(30),
    .doc-page-body > p:nth-of-type(31),
    .doc-page-body > h3:nth-of-type(15),
    .doc-page-body > p:nth-of-type(45),
    .doc-page-body > p:nth-of-type(46),
    .doc-page-body > p:nth-of-type(47),
    .doc-page-body > h3:nth-of-type(20),
    .doc-page-body > p:nth-of-type(62),
    .doc-page-body > p:nth-of-type(63),
    .doc-page-body > p:nth-of-type(64),
    .doc-page-body > h3:nth-of-type(25),
    .doc-page-body > p:nth-of-type(78),
    .doc-page-body > p:nth-of-type(79),
    .doc-page-body > p:nth-of-type(80),
    .doc-page-body > h3:nth-of-type(28),
    .doc-page-body > p:nth-of-type(87),
    .doc-page-body > p:nth-of-type(88),
    .doc-page-body > p:nth-of-type(89) { grid-column: 9 / 13; }

    /* … and two halves wherever a group has no third card, which is what keeps the grid hole-free */
    .doc-page-body > h3:nth-of-type(11),
    .doc-page-body > p:nth-of-type(32),
    .doc-page-body > p:nth-of-type(33),
    .doc-page-body > p:nth-of-type(34),
    .doc-page-body > h3:nth-of-type(16),
    .doc-page-body > p:nth-of-type(50),
    .doc-page-body > p:nth-of-type(51),
    .doc-page-body > p:nth-of-type(52),
    .doc-page-body > h3:nth-of-type(21),
    .doc-page-body > p:nth-of-type(66),
    .doc-page-body > p:nth-of-type(67),
    .doc-page-body > p:nth-of-type(68) { grid-column: 1 / 7; }
    .doc-page-body > h3:nth-of-type(12),
    .doc-page-body > p:nth-of-type(35),
    .doc-page-body > p:nth-of-type(36),
    .doc-page-body > p:nth-of-type(37),
    .doc-page-body > h3:nth-of-type(17),
    .doc-page-body > p:nth-of-type(53),
    .doc-page-body > p:nth-of-type(54),
    .doc-page-body > h3:nth-of-type(22),
    .doc-page-body > p:nth-of-type(69),
    .doc-page-body > p:nth-of-type(70),
    .doc-page-body > p:nth-of-type(71) { grid-column: 7 / 13; }
    .doc-page-body > p:nth-of-type(54) { grid-row: span 2; }

    /* the hairlines the sample rules its columns with: one down every column but the first … */
    .doc-page-body > h3:nth-of-type(6),
    .doc-page-body > p:nth-of-type(16),
    .doc-page-body > p:nth-of-type(17),
    .doc-page-body > p:nth-of-type(18),
    .doc-page-body > h3:nth-of-type(9),
    .doc-page-body > p:nth-of-type(26),
    .doc-page-body > p:nth-of-type(27),
    .doc-page-body > p:nth-of-type(28),
    .doc-page-body > h3:nth-of-type(14),
    .doc-page-body > p:nth-of-type(42),
    .doc-page-body > p:nth-of-type(43),
    .doc-page-body > p:nth-of-type(44),
    .doc-page-body > h3:nth-of-type(19),
    .doc-page-body > p:nth-of-type(59),
    .doc-page-body > p:nth-of-type(60),
    .doc-page-body > p:nth-of-type(61),
    .doc-page-body > h3:nth-of-type(24),
    .doc-page-body > p:nth-of-type(75),
    .doc-page-body > p:nth-of-type(76),
    .doc-page-body > p:nth-of-type(77),
    .doc-page-body > h3:nth-of-type(27),
    .doc-page-body > p:nth-of-type(84),
    .doc-page-body > p:nth-of-type(85),
    .doc-page-body > p:nth-of-type(86),
    .doc-page-body > h3:nth-of-type(7),
    .doc-page-body > p:nth-of-type(19),
    .doc-page-body > p:nth-of-type(20),
    .doc-page-body > p:nth-of-type(21),
    .doc-page-body > h3:nth-of-type(10),
    .doc-page-body > p:nth-of-type(29),
    .doc-page-body > p:nth-of-type(30),
    .doc-page-body > p:nth-of-type(31),
    .doc-page-body > h3:nth-of-type(15),
    .doc-page-body > p:nth-of-type(45),
    .doc-page-body > p:nth-of-type(46),
    .doc-page-body > p:nth-of-type(47),
    .doc-page-body > h3:nth-of-type(20),
    .doc-page-body > p:nth-of-type(62),
    .doc-page-body > p:nth-of-type(63),
    .doc-page-body > p:nth-of-type(64),
    .doc-page-body > h3:nth-of-type(25),
    .doc-page-body > p:nth-of-type(78),
    .doc-page-body > p:nth-of-type(79),
    .doc-page-body > p:nth-of-type(80),
    .doc-page-body > h3:nth-of-type(28),
    .doc-page-body > p:nth-of-type(87),
    .doc-page-body > p:nth-of-type(88),
    .doc-page-body > p:nth-of-type(89),
    .doc-page-body > h3:nth-of-type(12),
    .doc-page-body > p:nth-of-type(35),
    .doc-page-body > p:nth-of-type(36),
    .doc-page-body > p:nth-of-type(37),
    .doc-page-body > h3:nth-of-type(17),
    .doc-page-body > p:nth-of-type(53),
    .doc-page-body > p:nth-of-type(54),
    .doc-page-body > h3:nth-of-type(22),
    .doc-page-body > p:nth-of-type(69),
    .doc-page-body > p:nth-of-type(70),
    .doc-page-body > p:nth-of-type(71) { border-left: 1px solid var(--line); }

    /* … and one across, where a group runs on to a second row of cards (the name is the row's top edge) */
    .doc-page-body > h3:nth-of-type(11),
    .doc-page-body > h3:nth-of-type(12),
    .doc-page-body > h3:nth-of-type(26),
    .doc-page-body > h3:nth-of-type(27),
    .doc-page-body > h3:nth-of-type(28) { border-top: 1px solid var(--line); padding-top: 1.15rem; }
    /* the final block's break runs the width of its first row, the block wearing no bar of its own */
    .doc-page-body > h3:nth-of-type(24),
    .doc-page-body > h3:nth-of-type(25) { margin-top: 1.35rem; border-top: 1px solid var(--line); padding-top: 1.6rem; }
}

/* ── THE PRODUCT PAGE'S PICTURE FITS THE WINDOW (client, 2026-10-05: the HOSTAGRUND tin cut off at the bottom of
   its box on a desktop). The base lays the picture of a product's own page (ProductPage, .pp-media) out as a GRID
   ITEM at height: 100% — a percentage that resolves against the implicit track the photo's own intrinsic height
   sizes, so a tall pack shot overflowed the square box and its overflow: hidden cropped the tin. The base's card
   (.pc-media) solved the identical defect by taking the picture out of flow, and this does the same: the box keeps
   its shape (square beside the name, 4 : 3 on a phone), the picture is laid INSIDE its padding at the box's own
   size, and object-fit: contain keeps the tin's aspect ratio at every width. The box is also capped to the window's
   height, so on a short screen the whole tin still shows without scrolling past it. */
.pp-media { --pp-pad: clamp(14px, 3vw, 32px); position: relative; max-height: 72vh; max-height: 72dvh; }
.pp-media img {
    position: absolute;
    top: var(--pp-pad);
    left: var(--pp-pad);
    width: calc(100% - 2 * var(--pp-pad));
    height: calc(100% - 2 * var(--pp-pad));
    object-fit: contain;
}
@media (max-width: 760px) {
    .pp-media { max-height: 60vh; max-height: 60dvh; }
}
