/* =============================================================================
   Čaroděj — components & site chrome.
   Tokens live in app.css; nothing here hardcodes a colour that is not a
   one-off gradient stop of the gilding.
   ============================================================================= */

/* =============================================================================
   Buttons
   ============================================================================= */

.btn {
    display: inline-flex;
    gap: 0.6em;
    align-items: center;
    justify-content: center;
    padding: 0.78rem 1.7rem;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: 600;
    line-height: 1;
    color: var(--color-text);
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
    white-space: nowrap;
    cursor: pointer;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    transition:
        color var(--transition-fast),
        background-color var(--transition-fast),
        border-color var(--transition-fast),
        box-shadow var(--transition),
        transform var(--transition-fast);
}

.btn--sm {
    padding: 0.55rem 1.1rem;
    font-size: var(--text-2xs);
}

.btn--lg {
    padding: 1.05rem 2.5rem;
    font-size: var(--text-sm);
}

/* Gilded. Highlight at the top edge, shadow at the bottom — foil stamping,
   not a flat brand colour. Use at most once per view. */
.btn--primary {
    color: var(--color-text-inverse);
    background-image: linear-gradient(180deg, #f4e0b3 0%, #d8b36b 45%, #b78e44 100%);
    border-color: rgb(255 240 206 / 45%);
    box-shadow:
        inset 0 1px 0 rgb(255 255 255 / 45%),
        0 12px 28px -16px rgb(216 179 107 / 90%);
}

.btn--primary:hover {
    background-image: linear-gradient(180deg, #fbecd0 0%, #e5c384 45%, #c69c4f 100%);
    box-shadow:
        inset 0 1px 0 rgb(255 255 255 / 55%),
        0 16px 34px -14px rgb(216 179 107 / 100%);
}

.btn--secondary {
    color: var(--color-gold);
    background-color: rgb(216 179 107 / 4%);
    border-color: var(--color-gold-line);
}

.btn--secondary:hover {
    color: var(--color-gold-bright);
    background-color: var(--color-gold-wash);
    border-color: var(--color-gold-dim);
    box-shadow: var(--glow-gold);
}

.btn--ghost {
    color: var(--color-text-secondary);
}

.btn--ghost:hover {
    color: var(--color-gold);
    background-color: rgb(255 255 255 / 4%);
}

.btn:active:not(:disabled, [aria-disabled='true']) {
    transform: translateY(1px);
}

.btn:disabled,
.btn[aria-disabled='true'] {
    cursor: not-allowed;
    opacity: 0.58;
    box-shadow: none;
    transform: none;
}

.btn:disabled:hover,
.btn[aria-disabled='true']:hover {
    color: inherit;
    background-image: none;
    box-shadow: none;
}

.btn--primary:disabled,
.btn--primary[aria-disabled='true'] {
    color: var(--color-text-inverse);
    background-image: linear-gradient(180deg, #f4e0b3 0%, #d8b36b 45%, #b78e44 100%);
}

/* =============================================================================
   Cards
   ============================================================================= */

.card {
    position: relative;
    padding: var(--space-6);
    background-color: var(--color-surface);
    background-image: linear-gradient(180deg, rgb(255 255 255 / 4.5%), rgb(255 255 255 / 1.2%));
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    transition:
        border-color var(--transition),
        box-shadow var(--transition);
}

.card:hover {
    border-color: var(--color-gold-line);
    box-shadow:
        var(--shadow-md),
        inset 0 1px 0 rgb(240 216 162 / 14%),
        var(--glow-gold);
}

.card__eyebrow {
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
}

.card__title {
    margin-block-start: var(--space-2);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: var(--leading-snug);
}

.card__body {
    margin-block-start: var(--space-3);
    color: var(--color-text-secondary);
}

.card__footer {
    margin-block-start: var(--space-5);
    padding-block-start: var(--space-4);
    border-block-start: 1px solid var(--color-border);
}

/* The ornamented variant used for a reading: brass corner brackets on two
   opposite corners, the way a plate is mounted in an atlas. */
.card--reading {
    padding: var(--space-7) var(--space-6) var(--space-6);
    background-image:
        radial-gradient(ellipse 70% 40% at 50% 0%, rgb(216 179 107 / 7%), transparent 70%),
        linear-gradient(180deg, rgb(255 255 255 / 4.5%), rgb(255 255 255 / 1.2%));
}

.card--reading::before,
.card--reading::after {
    position: absolute;
    width: 16px;
    height: 16px;
    border: 1px solid var(--color-gold-line);
    content: '';
}

.card--reading::before {
    inset-block-start: 10px;
    inset-inline-start: 10px;
    border-block-end: 0;
    border-inline-end: 0;
}

.card--reading::after {
    inset-block-end: 10px;
    inset-inline-end: 10px;
    border-block-start: 0;
    border-inline-start: 0;
}

/* =============================================================================
   Forms
   ============================================================================= */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-text-secondary);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.label__optional {
    font-weight: 400;
    color: var(--color-text-muted);
    text-transform: none;
    letter-spacing: 0;
}

.input,
.textarea,
.select {
    width: 100%;
    padding: 0.72rem 0.9rem;
    font-size: var(--text-base);
    color: var(--color-text);
    background-color: rgb(255 255 255 / 3.5%);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    transition:
        border-color var(--transition-fast),
        background-color var(--transition-fast),
        box-shadow var(--transition-fast);
}

.textarea {
    min-height: 8rem;
    line-height: var(--leading-normal);
    resize: vertical;
}

.select {
    padding-inline-end: 2.5rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23d8b36b' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.95rem center;
    background-size: 12px;
    appearance: none;
}

.input::placeholder,
.textarea::placeholder {
    color: var(--color-text-muted);
    opacity: 1;
}

/* A single visible ring for pointer and keyboard alike — an input that only
   glows for keyboard users reads as broken to everyone else. */
.input:focus,
.textarea:focus,
.select:focus {
    background-color: rgb(255 255 255 / 5.5%);
    border-color: var(--color-gold-dim);
    outline: none;
    box-shadow: 0 0 0 3px rgb(216 179 107 / 20%);
}

.input:disabled,
.textarea:disabled,
.select:disabled {
    color: var(--color-text-muted);
    cursor: not-allowed;
    background-color: rgb(255 255 255 / 1.5%);
}

input[type='checkbox'],
input[type='radio'] {
    width: 1.05rem;
    height: 1.05rem;
    accent-color: var(--color-gold);
}

.choice {
    display: flex;
    gap: var(--space-3);
    align-items: center;
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

/* A consent label runs to two lines; without this the flex item shrinks and the
   box stops being square. */
.choice input[type='checkbox'],
.choice input[type='radio'] {
    flex: none;
}

/* A set of radios — the four outcomes of a follow-up (spec sec. 63). Stacked
   rather than side by side: the options are whole sentences, and a row of four
   would wrap differently at every breakpoint. */
.choices {
    display: grid;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.field__help {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

.field__error {
    display: flex;
    gap: 0.5em;
    align-items: baseline;
    font-size: var(--text-sm);
    color: var(--color-danger);
}

.field__error::before {
    font-size: 0.8em;
    content: '\25c6';
}

.field--invalid .input,
.field--invalid .textarea,
.field--invalid .select {
    border-color: rgb(226 113 107 / 55%);
}

.field--invalid .input:focus,
.field--invalid .textarea:focus,
.field--invalid .select:focus {
    box-shadow: 0 0 0 3px rgb(226 113 107 / 20%);
}

/* =============================================================================
   Badge
   ============================================================================= */

.badge {
    display: inline-flex;
    gap: 0.45em;
    align-items: center;
    padding: 0.3em 0.75em;
    font-size: var(--text-2xs);
    font-weight: 600;
    line-height: 1.4;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    background-color: var(--color-gold-wash);
    border: 1px solid var(--color-gold-line);
    border-radius: var(--radius-pill);
}

.badge--copper {
    color: var(--color-copper-hover);
    background-color: rgb(192 122 75 / 10%);
    border-color: var(--color-copper-line);
}

.badge--muted {
    color: var(--color-text-muted);
    background-color: rgb(255 255 255 / 3%);
    border-color: var(--color-border-strong);
}

.badge--solid {
    color: var(--color-text-inverse);
    background-image: linear-gradient(180deg, #f4e0b3, #c69c4f);
    border-color: transparent;
}

/* =============================================================================
   Ornamental divider — a ruled line broken by a small brass diamond.
   Used as <hr class="divider">, no children required.
   ============================================================================= */

.divider {
    position: relative;
    height: 1px;
    border: 0;

    /* The UA stylesheet hides overflow on <hr>, which would clip the diamond
       below to a one-pixel slice. */
    overflow: visible;
    background-image: linear-gradient(
        90deg,
        transparent,
        var(--color-gold-line) 16%,
        var(--color-gold-line) calc(50% - 12px),
        transparent calc(50% - 12px),
        transparent calc(50% + 12px),
        var(--color-gold-line) calc(50% + 12px),
        var(--color-gold-line) 84%,
        transparent
    );
}

.divider::after {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    width: 8px;
    height: 8px;
    border: 1px solid var(--color-gold);
    transform: translate(-50%, -50%) rotate(45deg);
    content: '';
}

.divider--short {
    width: 12rem;
    margin-inline: auto;
}

/* =============================================================================
   Flash messages
   ============================================================================= */

.flash-stack {
    display: grid;
    gap: var(--space-3);
    margin-block: var(--space-5);
}

.flash {
    display: flex;
    gap: var(--space-3);
    align-items: baseline;
    padding: var(--space-4) var(--space-5);
    font-size: var(--text-sm);
    color: var(--color-text);
    background-color: var(--color-surface);
    background-image: linear-gradient(90deg, rgb(255 255 255 / 4%), transparent 60%);
    border: 1px solid var(--color-border);
    border-inline-start: 2px solid var(--flash-accent, var(--color-gold));
    border-radius: var(--radius-sm);
}

.flash::before {
    flex: none;
    font-size: 0.7em;
    color: var(--flash-accent, var(--color-gold));
    content: '\25c6';
}

.flash--success {
    --flash-accent: var(--color-success);
}

.flash--error,
.flash--danger {
    --flash-accent: var(--color-danger);
}

.flash--warning {
    --flash-accent: var(--color-warning);
}

.flash--info,
.flash--notice {
    --flash-accent: var(--color-info);
}

/* =============================================================================
   Section header & overline
   ============================================================================= */

.overline {
    display: inline-flex;
    gap: 0.85em;
    align-items: center;
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
}

.overline::before {
    inline-size: 1.75rem;
    block-size: 1px;
    background-image: linear-gradient(90deg, transparent, var(--color-gold));
    content: '';
}

.overline--centered {
    justify-content: center;
}

.overline--centered::after {
    inline-size: 1.75rem;
    block-size: 1px;
    background-image: linear-gradient(90deg, var(--color-gold), transparent);
    content: '';
}

.section-header {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    align-items: var(--section-header-align, flex-start);
}

.section-header--centered {
    --section-header-align: center;

    text-align: center;
}

.section-header__title {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
}

.section-header__lede {
    max-width: 54ch;
    color: var(--color-text-secondary);
}

/* =============================================================================
   Site chrome — public header & footer
   ============================================================================= */

.site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 50;
    background-color: rgb(10 13 24 / 72%);
    border-block-end: 1px solid var(--color-border);
    backdrop-filter: blur(14px) saturate(140%);
}

.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4) var(--space-6);
    align-items: center;
    justify-content: space-between;
    min-block-size: 4.5rem;
    padding-block: var(--space-3);
}

.brand {
    display: inline-flex;
    gap: 0.7rem;
    align-items: center;
    color: var(--color-text);
    text-decoration: none;
}

.brand__mark {
    flex: none;
    color: var(--color-gold);
    transition: transform var(--transition-slow), filter var(--transition);
}

.brand:hover .brand__mark {
    filter: drop-shadow(0 0 10px rgb(216 179 107 / 55%));
    transform: rotate(45deg);
}

.brand__word {
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.14em;
}

.site-nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-6);
    align-items: center;
}

.site-nav__link {
    position: relative;
    padding-block: 0.4rem;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--color-text-secondary);
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    transition: color var(--transition-fast);
}

.site-nav__link::after {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: 1px;
    background-color: var(--color-gold);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition);
    content: '';
}

.site-nav__link:hover,
.site-nav__link[aria-current='page'] {
    color: var(--color-gold);
}

.site-nav__link:hover::after,
.site-nav__link[aria-current='page']::after {
    transform: scaleX(1);
}

.site-footer {
    margin-block-start: var(--space-9);
    padding-block: var(--space-7) var(--space-6);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    background-image: linear-gradient(180deg, transparent, rgb(6 8 15 / 85%));
    border-block-start: 1px solid var(--color-border);
}

.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    align-items: center;
    justify-content: space-between;
}

.site-footer__brand {
    display: flex;
    gap: 0.6rem;
    align-items: center;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--color-text-secondary);
}

.footer-nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
}

.footer-nav a {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.footer-nav a:hover {
    color: var(--color-gold);
}

/* =============================================================================
   Site chrome — application shell (signed-in). Grows in M2.
   ============================================================================= */

.app-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 50;
    background-color: rgb(10 13 24 / 84%);
    border-block-end: 1px solid var(--color-border);
    backdrop-filter: blur(14px);
}

.app-header__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: center;
    justify-content: space-between;
    min-block-size: 3.6rem;
    padding-block: var(--space-2);
}

.app-header .brand__word {
    font-size: 1.15rem;
}

.user-chip {
    display: inline-flex;
    gap: 0.6rem;
    align-items: center;
    padding: 0.3rem 0.9rem 0.3rem 0.3rem;
    font-size: var(--text-xs);
    color: var(--color-text-secondary);
    letter-spacing: var(--tracking-wide);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
}

/* The chip became a link in M2a; the global underline for <a> would turn it
   into a strange gilded pill. */
a.user-chip {
    text-decoration: none;
    transition:
        color var(--transition-fast),
        border-color var(--transition-fast);
}

a.user-chip:hover {
    color: var(--color-text);
    border-color: var(--color-gold-line);
}

.user-chip__avatar {
    display: grid;
    place-items: center;
    inline-size: 1.85rem;
    block-size: 1.85rem;
    font-size: var(--text-2xs);
    font-weight: 700;
    color: var(--color-text-inverse);
    background-image: linear-gradient(180deg, #f4e0b3, #b78e44);
    border-radius: 50%;
}

/* =============================================================================
   Site chrome — admin. Utilitarian on purpose: no ornament, no sky, denser
   rhythm, wider measure. Applied through the body_class block.
   ============================================================================= */

.is-admin {
    --container: 84rem;
    --text-base: 0.9375rem;

    background-image: none;
}

.is-admin::before,
.is-admin::after {
    display: none;
}

/* Headings in the body font, not the display serif.
   Cormorant is the brand's voice and it is the wrong voice here: these are
   labels on a control panel, not titles on a page somebody came to read, and at
   a glance a serif "Podle modelu" reads as prose the eye should slow down for.
   The rest of the site keeps it; this is the one area that is a tool. */
.is-admin h1,
.is-admin h2,
.is-admin h3,
.is-admin h4 {
    font-family: var(--font-body);
    font-weight: 600;
    letter-spacing: normal;
}

.admin-main h2 {
    margin-block-end: 0;
    font-size: var(--text-lg);
}

.admin-main h3 {
    margin-block-end: 0;
    font-size: var(--text-base);
}

.admin-header {
    background-color: var(--color-bg-deep);
    border-block-end: 1px solid var(--color-border-strong);
}

.admin-header__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: center;
    justify-content: space-between;
    min-block-size: 3rem;
    padding-block: var(--space-2);
}

.admin-brand {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: 700;
    color: var(--color-text);
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.admin-brand span {
    color: var(--color-gold);
}

.admin-whoami {
    display: flex;
    gap: var(--space-4);
    align-items: baseline;
    margin: 0;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

/* The shell: a fixed left rail and everything else. `minmax(0, 1fr)` rather
   than `1fr` is load-bearing — without it a wide table stretches the column
   instead of scrolling inside .table-scroll, and the whole page gets a
   horizontal scrollbar. */
.admin-shell {
    display: grid;
    grid-template-columns: 10rem minmax(0, 1fr);
    gap: var(--space-6);
    align-items: start;
    padding-block: var(--space-5);
}

@media (width < 48rem) {
    .admin-shell {
        grid-template-columns: minmax(0, 1fr);
    }
}

.admin-rail {
    position: sticky;
    inset-block-start: var(--space-4);
}

.admin-rail__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

@media (width < 48rem) {
    .admin-rail {
        position: static;
    }

    .admin-rail__list {
        flex-direction: row;
        flex-wrap: wrap;
    }
}

.admin-rail__link {
    display: block;
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    border-radius: var(--radius-sm);
}

.admin-rail__link:hover {
    color: var(--color-text);
    background-color: var(--color-surface);
}

.admin-rail__link.is-current {
    color: var(--color-gold);
    background-color: var(--color-gold-wash);
}

.admin-main {
    min-inline-size: 0;
}

/* Page heading inside the shell. Smaller than the site's section-header: this
   is a tool, and the title is a label rather than a piece of writing. */
.admin-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-4);
    align-items: baseline;
    justify-content: space-between;
}

.admin-head h1 {
    margin: 0;
    font-size: var(--text-xl);
}

.admin-head__note {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

/* Sub-navigation within a section (AI: náklady / role / prompty / requesty). */
.admin-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding-block-end: var(--space-2);
    font-size: var(--text-xs);
    border-block-end: 1px solid var(--color-border);
}

.admin-tabs a {
    color: var(--color-text-muted);
    text-decoration: none;
}

.admin-tabs a:hover {
    color: var(--color-text);
}

.admin-tabs a.is-current {
    color: var(--color-gold);
}

/* KPI cards — the dashboard's one big number per box (spec sec. 106). Auto-fit
   rather than a fixed count so the row reflows without a media query per
   breakpoint. */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--space-3);
}

.kpi {
    padding: var(--space-4);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.kpi__label {
    margin: 0;
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.kpi__value {
    margin: var(--space-2) 0 0;
    font-family: var(--font-mono);
    font-size: var(--text-2xl);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    color: var(--color-text);
}

.kpi__value--negative {
    color: var(--color-copper-hover);
}

.kpi__value--positive {
    color: var(--color-success);
}

.kpi__meta {
    margin: var(--space-1) 0 0;
    font-size: var(--text-2xs);
    color: var(--color-text-muted);
}

/* A standing caveat above a screen — the AI cost pages carry one because the
   price table they are computed from is admittedly a guess (config/packages/
   ai.yaml). Not a flash: it is a property of the page, not of the request. */
.admin-notice {
    padding: var(--space-3) var(--space-4);
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    border: 1px solid var(--color-copper-line);
    border-inline-start: 3px solid var(--color-copper);
    border-radius: var(--radius-sm);
}

.admin-notice strong {
    color: var(--color-warning);
}

/* Filter bar above a list. */
.admin-filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    align-items: flex-end;
}

/* Simple LIMIT/OFFSET pager: previous, position, next. */
.admin-pager {
    display: flex;
    gap: var(--space-4);
    align-items: baseline;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
}

/* Key/value detail block — a payment, a request, a subscription. */
.admin-facts {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-2) var(--space-4);
    margin: 0;
    font-size: var(--text-sm);
}

.admin-facts dt {
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.admin-facts dd {
    margin: 0;
    overflow-wrap: anywhere;
}

/* Read-only dump of a prompt body, a JSON schema or a webhook payload. */
.admin-pre {
    max-block-size: 28rem;
    margin: 0;
    padding: var(--space-3);
    overflow: auto;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background-color: var(--color-bg-deep);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

/* Dense rows for the admin: the site-wide .data-table padding is generous for
   a four-column statement and wasteful for a fourteen-column request log. */
.data-table--dense th,
.data-table--dense td {
    padding: var(--space-2) var(--space-3);
}

/* A secondary line under a cell's main value — the raw event name under a
   Czech funnel label, a note under a ledger reason. `.field__help` is an inline
   element in a form, where it sits beside its control; in a table cell the two
   run together on one line and the eye cannot tell which is which. */
.data-table .field__help {
    display: block;
    margin-block-start: var(--space-1);
}

/* =============================================================================
   Auth pages — login, registration, password reset.
   Nothing new is invented here: the plate is a .card and every control comes
   from the form section above. These rules only give the four screens their
   measure and centre them.
   ============================================================================= */

.auth {
    padding-block: clamp(var(--space-6), 8vh, var(--space-9));
}

.auth__plate {
    max-width: 30rem;
    padding: clamp(var(--space-5), 5vw, var(--space-7));
    margin-inline: auto;
}

/* The card's hover lift belongs to things you click. A form you spend a minute
   typing into must not pulse under the cursor, so it is cancelled here. */
.auth__plate:hover {
    border-color: var(--color-border);
    box-shadow: var(--shadow-md);
}

/* The only full-width button in the design system: on a single-purpose form the
   primary action is the page, and a 12rem button floating in a 30rem plate
   reads as an afterthought. */
.auth__submit {
    width: 100%;

    /* On top of the .stack rhythm: the last thing above the button is usually a
       consent line whose text box ends flush with its own baseline, so the
       inherited gap reads tighter here than everywhere else. */
    margin-block-start: var(--space-3);
}

.auth__link,
.auth__footnote {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    text-align: center;
}

.auth__footnote {
    max-width: 30rem;
    margin-block-start: var(--space-5);
    margin-inline: auto;
}

/* =============================================================================
   Account page
   ============================================================================= */

.account-fact {
    display: grid;
    gap: var(--space-3);
    justify-items: start;
}

.account-code {
    font-size: var(--text-xl);
    font-weight: 600;
    color: var(--color-gold);
    letter-spacing: 0.28em;
}

/* The data-export requests on /ucet/gdpr. Still a <ul> for screen readers, but
   without markers: every row already opens with a status badge, and a bullet
   next to it reads as two bullets. */
.export-list {
    display: grid;
    gap: var(--space-4);
    width: 100%;
    padding: 0;
    margin: 0;
    list-style: none;
}

.export-list > li {
    display: grid;
    gap: var(--space-2);
    justify-items: start;
}

/* =============================================================================
   Landing page
   ============================================================================= */

.hero {
    position: relative;
    display: grid;
    place-items: center;
    min-block-size: min(72vh, 38rem);
    padding-block: clamp(2.5rem, 6vh, 4rem) clamp(2rem, 5vh, 3.5rem);
    overflow: hidden;
}

.hero__backdrop {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* A watermark, not a motif: big enough to feel like an instrument etched into
   the paper, faint enough that the headline still owns the centre. */
.hero__ghost {
    position: absolute;
    inset-block-start: 29%;
    inset-inline-start: 50%;
    inline-size: min(80vw, 23rem);
    block-size: auto;
    color: var(--color-gold);
    opacity: 0.045;
    translate: -50% -50%;
    animation: drift 320s linear infinite;
}

.hero__constellation {
    position: absolute;
    color: var(--color-gold);
    opacity: 0.26;
}

.hero__constellation--top {
    inset-block-start: 0;
    inset-inline-end: -6%;
    inline-size: min(34rem, 56vw);
}

.hero__constellation--bottom {
    inset-block-end: 0;
    inset-inline-start: -9%;
    inline-size: min(22rem, 40vw);
    opacity: 0.18;
    scale: -1 1;
}

/* The plate: hairline margins down both sides, brass brackets on two
   opposite corners. */
.hero__plate {
    position: relative;
    padding: clamp(1.75rem, 4vw, 3rem) clamp(1.25rem, 4vw, 3rem);
    text-align: center;
}

.hero__plate::before,
.hero__plate::after {
    position: absolute;
    inline-size: 26px;
    block-size: 26px;
    border: 1px solid var(--color-gold-dim);
    content: '';
}

.hero__plate::before {
    inset-block-start: 0;
    inset-inline-start: 0;
    border-block-end: 0;
    border-inline-end: 0;
}

.hero__plate::after {
    inset-block-end: 0;
    inset-inline-end: 0;
    border-block-start: 0;
    border-inline-start: 0;
}

.hero__sigil {
    color: var(--color-gold);
    filter: drop-shadow(0 0 22px rgb(216 179 107 / 40%));
    margin-inline: auto;
}

.hero__overline {
    margin-block-start: var(--space-5);
}

.hero__title {
    margin-block-start: var(--space-4);
    font-size: var(--text-display);
    font-weight: 600;
    line-height: 1.04;
    letter-spacing: -0.02em;
}

/* The name itself is gilded — a single foil-stamped word in the headline. */
.hero__gild {
    display: inline-block;
    color: var(--color-gold);
    background-image: linear-gradient(170deg, #f6e4bb 10%, #d8b36b 52%, #b0873f 92%);
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hero__lede {
    max-width: 48ch;
    margin-block-start: var(--space-5);
    margin-inline: auto;
    font-size: var(--text-base);
    line-height: 1.72;
    color: var(--color-text-secondary);
}

.hero__lede strong {
    font-weight: 500;
    color: var(--color-text);
}

.hero__divider {
    width: 14rem;
    margin-block: var(--space-5);
    margin-inline: auto;
}

.hero__note {
    margin-block-start: var(--space-4);
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold-dim);
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
}

/* The hero's question field (spec sec. 80). One input and one button, side by
   side where there is room and stacked where there is not — the input is what
   the page is for, so it takes the space and the button never wraps. */
.hero__ask {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    justify-content: center;
    max-width: 34rem;
    margin-inline: auto;
}

.hero__ask .input {
    flex: 1 1 18rem;
    padding-block: 0.95rem;
    text-align: center;
}

@media (min-width: 34rem) {
    .hero__ask .input {
        text-align: start;
    }
}

.hero__ask .btn {
    flex: 0 0 auto;
}

.hero__alt {
    margin-block-start: var(--space-4);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

/* =============================================================================
   Homepage feature rows — one discipline per row: copy on one side, an
   engraved panel on the other, and a hairline between rows rather than card
   chrome around each. Cards would make five sections look like five products;
   these are meant to read as chapters.

     <article class="feature-row">
       <div class="feature-row__body stack">…</div>
       <div class="feature-row__art">…svg…</div>
     </article>
   ============================================================================= */

.feature-row {
    display: grid;
    gap: var(--space-6);
    align-items: center;
    padding-block: var(--space-7);
    border-block-start: 1px solid var(--color-border);
}

@media (min-width: 52rem) {
    .feature-row {
        grid-template-columns: 1.1fr 0.9fr;
    }

    /* Alternating sides, so a column of rows does not read as a list. The art
       moves rather than the copy: the text should always start at the same
       optical place down the page. */
    .feature-row--mirrored .feature-row__art {
        order: -1;
    }
}

.feature-row__art {
    display: grid;
    place-items: center;
    min-block-size: 12rem;
    padding: var(--space-6);
    background-image:
        radial-gradient(ellipse 60% 60% at 50% 40%, rgb(216 179 107 / 8%), transparent 70%);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.feature-row__glyph {
    inline-size: min(11rem, 60%);
    block-size: auto;
    color: var(--color-gold-dim);
}

.feature-row--soon .feature-row__body {
    /* A teaser for something that does not exist yet steps back, so it cannot
       be mistaken for something on sale. */
    color: var(--color-text-muted);
}

/* =============================================================================
   "Jak to funguje" — three numbered steps, ruled rather than boxed.
   ============================================================================= */

.steps {
    display: grid;
    gap: var(--space-5);
    padding: 0;
    margin: 0;
    list-style: none;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    counter-reset: step;
}

.steps > li {
    padding-block-start: var(--space-4);
    border-block-start: 1px solid var(--color-gold-line);
    counter-increment: step;
}

.steps > li::before {
    display: block;
    margin-block-end: var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 600;
    line-height: 1;
    color: var(--color-gold);
    content: counter(step, decimal-leading-zero);
}

.step__name {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 600;
}

.step__note {
    margin-block-start: var(--space-2);
    color: var(--color-text-secondary);
}

/* =============================================================================
   "Ukázka výkladu" — a real reading, plainly labelled as a specimen.

   Set slightly smaller and inside a dashed rule, because the one thing this
   block must never do is read as the visitor's own reading.
   ============================================================================= */

.sample {
    position: relative;
    padding: var(--space-6);
    border: 1px dashed var(--color-gold-line);
    border-radius: var(--radius-md);
}

.sample__mark {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: var(--space-5);
    padding-inline: var(--space-3);
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-widest);
    background-color: var(--color-bg);
    translate: 0 -50%;
}

.sample__question {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-style: italic;
    color: var(--color-text-secondary);
}

/* =============================================================================
   The lead magnet's card-of-the-day plate and address form (spec sec. 83).
   ============================================================================= */

.daily-card {
    display: grid;
    gap: var(--space-6);
    align-items: start;
}

@media (min-width: 40rem) {
    .daily-card {
        grid-template-columns: 12rem 1fr;
    }
}

.daily-card__plate {
    min-height: 15rem;
}

.lead-capture__form {
    max-width: 30rem;
}

/* The triad: three disciplines separated by hairlines, no card chrome.
   Stacked and ruled horizontally by default; the vertical rules only appear
   once all three really sit on one row, so no item ever carries a leading rule
   at the start of a line. */
.triad {
    display: grid;
    grid-template-columns: 1fr;
    border-block-start: 1px solid var(--color-border);
}

.triad__item {
    padding: var(--space-6) var(--space-5);
    text-align: center;
    border-block-end: 1px solid var(--color-border);
}

@media (min-width: 48rem) {
    .triad {
        grid-template-columns: repeat(3, 1fr);
        border-block-end: 1px solid var(--color-border);
    }

    .triad__item {
        border-block-end: 0;
        border-inline-start: 1px solid var(--color-border);
    }

    .triad__item:first-child {
        border-inline-start: 0;
    }
}

.triad__glyph {
    margin-inline: auto;
    color: var(--color-gold-dim);
    transition: color var(--transition), filter var(--transition);
}

.triad__item:hover .triad__glyph {
    color: var(--color-gold);
    filter: drop-shadow(0 0 14px rgb(216 179 107 / 45%));
}

.triad__name {
    margin-block-start: var(--space-4);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.16em;
}

.triad__note {
    margin-block-start: var(--space-2);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

/* =============================================================================
   Price plates — the ceník (spec sec. 68).

   A card that has to be scannable in a column of near-identical cards, so the
   only things allowed to be loud are the name and the number. Everything else
   is hairline and small-caps: the amount carries the gold, the card does not.

   Markup:

     <article class="card price-card">
         <p class="card__eyebrow">…</p>
         <h3 class="price-card__name">…</h3>
         <p class="price-card__amount">79 Kč <span class="price-card__unit">…</span></p>
         <p class="price-card__note">…</p>
         <p class="price-card__credits">…</p>
         <div class="price-card__cta">…</div>
     </article>
   ============================================================================= */

.price-grid {
    display: grid;
    gap: var(--space-5);
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

/* Column, so the call to action can be pushed to the bottom edge and every
   plate in a row ends on the same line however long the copy above it is. */
.price-card {
    display: flex;
    flex-direction: column;
}

.price-card__name {
    margin-block-start: var(--space-2);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: var(--leading-snug);
}

.price-card__amount {
    margin-block-start: var(--space-4);
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    color: var(--color-gold-bright);
    letter-spacing: var(--tracking-tight);
}

.price-card__unit {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.price-card__note {
    margin-block-start: var(--space-3);
    color: var(--color-text-secondary);
}

.price-card__credits {
    margin-block-start: var(--space-3);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

/* margin-block-start: auto is what pins the button to the bottom of the plate. */
.price-card__cta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    margin-block-start: auto;
    padding-block-start: var(--space-5);
}

/* =============================================================================
   Data table — the credit statement, and anything else that is genuinely
   tabular. Ruled rather than striped: stripes on an ink background read as
   noise, and a hairline is the same device the rest of the system uses.

   Always wrapped in <div class="table-scroll"> so a narrow screen scrolls the
   table and not the page.
   ============================================================================= */

.table-scroll {
    overflow-x: auto;
}

.data-table {
    inline-size: 100%;
    font-size: var(--text-sm);
    border-collapse: collapse;
}

.data-table th,
.data-table td {
    padding: var(--space-3) var(--space-4);
    text-align: start;
    vertical-align: top;
    border-block-end: 1px solid var(--color-border);
}

.data-table th {
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    white-space: nowrap;
    border-block-end-color: var(--color-gold-line);
}

.data-table tbody tr:last-child td {
    border-block-end: 0;
}

.data-table__num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    text-align: end;
    white-space: nowrap;
}

/* Sign carries the meaning in a ledger, so it carries the colour too. */
.data-table__num--positive {
    color: var(--color-success);
}

.data-table__num--negative {
    color: var(--color-copper-hover);
}

.data-table__when {
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* =============================================================================
   Balance plate — one number, said once, at the top of /ucet/kredity.
   ============================================================================= */

.balance {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    align-items: baseline;
}

.balance__amount {
    font-family: var(--font-display);
    font-size: var(--text-4xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    color: var(--color-gold-bright);
    letter-spacing: var(--tracking-tight);
}

.balance__unit {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

/* =============================================================================
   Notifications — the inbox at /ucet/oznameni (spec sec. 76).

   One rule, and it only has to do one thing: say which plates are already
   read. The unread ones are the default card, at full contrast; a read one
   steps back. That way "new" needs no colour of its own — the badge says it in
   words, and the contrast says it again for anyone skimming.

   Markup:

     <div class="card stack notification--read">…</div>
   ============================================================================= */

.notification--read .card__title,
.notification--read .card__body {
    color: var(--color-text-muted);
}

.notification--read .card__eyebrow {
    color: var(--color-text-muted);
}

/* =============================================================================
   The drawn cards — a row of engraved plates at the head of a reading
   (spec sec. 112).

   There is no artwork yet and there will not be for some time, so a card is
   typeset rather than illustrated: a tall plate, a hairline rule, the position
   above and the name below, in the display face. That is a deliberate choice
   and not a placeholder — an atlas of engraved plates is the aesthetic, and a
   row of grey image boxes waiting for pictures would look unfinished in a way
   that this does not.

   Reversed cards are marked in the copy, never by rotating the plate. Turning
   the text upside down makes it unreadable to everybody and unreadable *twice*
   to a screen reader.

       <ol class="card-row">
         <li class="card-plate card-plate--reversed">
           <p class="card-plate__position">…</p>
           <p class="card-plate__name">…</p>
           <p class="card-plate__orientation">…</p>
         </li>
       </ol>
   ============================================================================= */

.card-row {
    display: grid;
    gap: var(--space-4);
    padding: 0;
    margin: 0;
    list-style: none;
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
}

.card-plate {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    align-items: center;
    justify-content: center;
    min-height: 11rem;
    padding: var(--space-4) var(--space-3);
    text-align: center;
    background-image:
        radial-gradient(ellipse 80% 50% at 50% 0%, rgb(216 179 107 / 9%), transparent 70%),
        linear-gradient(180deg, var(--color-surface-2), var(--color-surface));
    border: 1px solid var(--color-gold-line);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm), var(--glow-inset);
}

/* A copper hairline down the inner edge — the brass mount of a plate. */
.card-plate::before {
    position: absolute;
    inset: 5px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-xs);
    content: '';
    pointer-events: none;
}

.card-plate--reversed {
    border-color: var(--color-copper-line);
}

.card-plate__position {
    font-size: var(--text-2xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.card-plate__name {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    color: var(--color-gold-bright);
}

.card-plate__orientation {
    font-size: var(--text-2xs);
    color: var(--color-copper-hover);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

/* =============================================================================
   A reading's prose. One block per section, so the vertical rhythm of a
   thousand words is set once rather than by whatever the model's paragraph
   lengths happen to be.
   ============================================================================= */

.reading-section__title {
    margin-block-end: var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    color: var(--color-text);
}

/* The short answer is the one paragraph everybody reads, and often the only
   one somebody remembers a week later. Set larger, on gold, and given the
   plate's own ground. */
.reading-section--summary {
    padding: var(--space-5);
    background-color: var(--color-gold-wash);
    border: 1px solid var(--color-gold-line);
    border-radius: var(--radius-sm);
}

.reading-section--summary .reading-section__body {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    line-height: var(--leading-relaxed);
    color: var(--color-text);
}

.reading-section__body p {
    margin-block-end: var(--space-4);
}

.reading-section__body p:last-child {
    margin-block-end: 0;
}

/* The three lists. A marker per kind, because "co vám nahrává" and "na co si
   dát pozor" are opposite advice and must not look identical at a glance. */
.reading-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: 0;
    margin: 0;
    list-style: none;
}

.reading-list > li {
    position: relative;
    padding-inline-start: var(--space-5);
}

.reading-list > li::before {
    position: absolute;
    inset-inline-start: 0;
    color: var(--color-gold);
    content: '◆';
    font-size: var(--text-xs);
    line-height: 1.6;
}

.reading-list--positive > li::before {
    color: var(--color-success);
}

.reading-list--warning > li::before {
    color: var(--color-warning);
}

/* Follow-up questions are buttons, not bullets: clicking one starts the next
   reading with the question already written (spec sec. 113). */
.reading-followups {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* =============================================================================
   The waiting plate — what somebody looks at while the reading is written.
   ============================================================================= */

.reading-wait {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    align-items: center;
    padding-block: var(--space-7);
    text-align: center;
}

.reading-wait__title {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: 600;
    color: var(--color-gold-bright);
}

/* A slow pulse rather than a spinner. A spinner says "this is taking too long";
   this says "something is happening", which is the truth about a job that
   takes half a minute. */
.reading-wait__sigil {
    color: var(--color-gold);
    animation: reading-pulse 3.2s ease-in-out infinite;
}

@keyframes reading-pulse {
    0%, 100% { opacity: 0.35; }
    50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .reading-wait__sigil {
        animation: none;
        opacity: 0.8;
    }
}

/* =============================================================================
   The paywall (spec sec. 82).

   Sits directly under the last free section of a reading and has one job: make
   it obvious that the page stops rather than ends. The fade above it is what
   does that — a plate that simply began would read as the end of the reading,
   and somebody who thinks they have read it all does not pay.

   The fade is drawn by the wrapper, over the section above it, so no section
   template has to know it is the last free one.

     <div class="paywall-fade"></div>
     <div class="card paywall stack">…</div>
   ============================================================================= */

.paywall-fade {
    height: 5.5rem;

    /* Pulled up over the section above, so the text really does dissolve
       instead of a grey band appearing beneath it. The .stack gap is cancelled
       by the same amount. */
    margin-block: calc(var(--space-5) * -1 - 5.5rem) 0;
    background-image: linear-gradient(180deg, transparent, var(--color-bg) 92%);
    pointer-events: none;
}

.paywall {
    text-align: center;
    background-image:
        radial-gradient(ellipse 70% 60% at 50% 0%, rgb(216 179 107 / 12%), transparent 72%),
        linear-gradient(180deg, rgb(255 255 255 / 5%), rgb(255 255 255 / 1.2%));
    border-color: var(--color-gold-line);
}

.paywall:hover {
    box-shadow: var(--shadow-md);
}

.paywall__lock {
    margin-inline: auto;
    color: var(--color-gold);
}

.paywall__title {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: var(--leading-snug);
}

.paywall__price {
    font-family: var(--font-display);
    font-size: var(--text-4xl);
    font-weight: 600;
    line-height: var(--leading-tight);
    color: var(--color-gold-bright);
    letter-spacing: var(--tracking-tight);
}

.paywall__note {
    max-width: 44ch;
    margin-inline: auto;
    color: var(--color-text-secondary);
}

/* What is still behind it, as a list of headings without their text. Naming
   the parts is the offer; showing a word of them would be giving it away. */
.paywall__contents {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    justify-content: center;
    padding: 0;
    margin: 0;
    list-style: none;
}

.paywall__contents > li {
    padding: 0.3em 0.8em;
    font-size: var(--text-2xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius-pill);
}

/* =============================================================================
   The reading list at /vyklad/moje — a plate per reading, its status and the
   first sentence of it.
   ============================================================================= */

.reading-row__head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    align-items: baseline;
    justify-content: space-between;
}

.reading-row__teaser {
    display: -webkit-box;
    overflow: hidden;
    color: var(--color-text-secondary);
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

/* =============================================================================
   The Grimoár at /grimoar — a year of somebody's life as a ruled thread
   (spec sec. 64–65).

   The visual idea is the margin of a bound ledger: a hairline down the left,
   a brass stud per entry, months as engraved headings. It is the one screen in
   the application that is meant to look *long* — the length is the point, and
   an account with three years in it should feel like it has three years in it.
   ============================================================================= */

.timeline {
    --timeline-gutter: var(--space-6);
}

/* The month heading. Small caps and a gold hairline running off to the right,
   so the eye can find the year boundaries while scrolling past a decade. */
.timeline__month {
    display: flex;
    gap: var(--space-4);
    align-items: center;
    margin-bottom: var(--space-4);
    font-family: var(--font-body);
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
}

.timeline__month::after {
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, var(--color-gold-line), transparent);
    content: "";
}

/* The ruled margin. A pseudo-element rather than a border on the list so that
   it stops at the last entry instead of running under the month gap below. */
.timeline__entries {
    position: relative;
    padding-left: var(--timeline-gutter);
    margin: 0;
    list-style: none;
}

.timeline__entries::before {
    position: absolute;
    top: 0.6em;
    bottom: 0.6em;
    left: 5px;
    width: 1px;
    background: var(--color-border);
    content: "";
}

.timeline__entries > li + li {
    margin-top: var(--space-5);
}

/* The stud. Hollow for an ordinary entry, filled for one the customer answered
   — a Grimoár where the person wrote something back should show it at a
   glance. */
.timeline-entry {
    position: relative;
}

.timeline-entry::before {
    position: absolute;
    top: 0.55em;
    left: calc(-1 * var(--timeline-gutter) + 1px);
    width: 9px;
    height: 9px;
    border: 1px solid var(--color-gold-dim);
    border-radius: var(--radius-pill);
    background: var(--color-bg);
    content: "";
}

.timeline-entry--answered::before {
    border-color: var(--color-gold);
    background: var(--color-gold);
}

.timeline-entry__head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    align-items: baseline;
}

.timeline-entry__when {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

.timeline-entry__title {
    margin: var(--space-1) 0 0;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    line-height: var(--leading-snug);
    color: var(--color-text);
}

.timeline-entry__body {
    display: -webkit-box;
    overflow: hidden;
    margin: var(--space-2) 0 0;
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}

/* =============================================================================
   The theme statistics block (spec sec. 65) — "za poslední rok jste 17× řešil
   práci". A bar chart drawn in one gradient per row, because a chart library
   for five numbers would be a dependency for five numbers.
   ============================================================================= */

.theme-list {
    display: grid;
    gap: var(--space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.theme-row {
    display: grid;
    grid-template-columns: minmax(6rem, 10rem) 1fr auto;
    gap: var(--space-3);
    align-items: center;
    font-size: var(--text-sm);
}

.theme-row__name {
    overflow: hidden;
    color: var(--color-text-secondary);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.theme-row__bar {
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-2);
}

.theme-row__fill {
    display: block;
    height: 100%;
    border-radius: var(--radius-pill);
    background: linear-gradient(to right, var(--color-gold-deep), var(--color-gold));
}

.theme-row__count {
    color: var(--color-gold);
    font-variant-numeric: tabular-nums;
}

/* The filter chips above the timeline. A link per option, the active one
   inverted, and a "vše" that clears everything. */
.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.filter-chip {
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    color: var(--color-text-secondary);
    font-size: var(--text-xs);
    text-decoration: none;
    transition: border-color var(--transition-fast), color var(--transition-fast);
}

.filter-chip:hover {
    border-color: var(--color-gold-line);
    color: var(--color-text);
}

.filter-chip--active {
    border-color: var(--color-gold);
    background: var(--color-gold-wash);
    color: var(--color-gold-bright);
}

/* =============================================================================
   Chat — the AI Čaroděj (M11, spec sec. 58–60)

   The one screen in the application that is a conversation rather than a
   document, and the design has to say so without leaving the observatory: no
   speech-bubble tails, no avatars, no colour-coded chat app. Two registers
   instead — the person's words on a plain recessed plate, the Čaroděj's in the
   display serif on the surface the rest of the site uses for what it has
   written. The difference between "what you said" and "what was said to you" is
   then the same difference the site already makes between a form and a reading.
   ============================================================================= */

.chat-thread {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.chat-turn {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-width: 46ch;
}

/* Right for the person, left for the Čaroděj. margin-inline-start rather than
   align-self, so the plate keeps its own width and only its position moves. */
.chat-turn--user {
    margin-inline-start: auto;
    align-items: flex-end;
}

.chat-turn--wizard {
    margin-inline-end: auto;
}

.chat-turn__who {
    color: var(--color-text-muted);
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
}

.chat-turn__body {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    line-height: var(--leading-normal);
    /* The person's own words survive their own line breaks. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.chat-turn--user .chat-turn__body {
    background: var(--color-bg-deep);
    color: var(--color-text-secondary);
}

.chat-turn--wizard .chat-turn__body {
    border-color: var(--color-gold-line);
    background: var(--color-surface);
    box-shadow: var(--glow-inset);
    color: var(--color-text);
    font-family: var(--font-display);
    font-size: var(--text-lg);
}

/* "Čaroděj listuje vaším Grimoárem…" — the record that a tool ran. A rule with
   the sentence sitting on it: quieter than a message, and clearly not one. */
.chat-activity {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-style: italic;
}

.chat-activity::before,
.chat-activity::after {
    flex: 1;
    height: 1px;
    background: var(--color-gold-line);
    content: '';
    opacity: 0.5;
}

/* The compose box — the form itself, so the textarea, the counter and the
   button share one plate and read as a single control. */
.chat-compose {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: var(--shadow-md);
}

.chat-compose .textarea {
    resize: vertical;
}

.chat-compose__actions {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
}

/* "Dnes máte ještě 3 zprávy zdarma." Small, factual and always visible: a price
   somebody finds out about afterwards is a price they complain about. */
.chat-quota {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--text-xs);
}

.chat-quota--paid {
    color: var(--color-warning);
}

/* One row of the thread list. The whole row is the link, so the target is the
   plate and not the four words on it. */
.conversation-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-border);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--transition-fast);
}

.conversation-row:hover {
    border-color: var(--color-gold-line);
}

.conversation-row:hover .conversation-row__title {
    color: var(--color-gold-bright);
}

.conversation-row__title {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    transition: color var(--transition-fast);
}

.conversation-row__when {
    flex: none;
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}

@media (width <= 40rem) {
    .chat-turn {
        max-width: 100%;
    }
}

/* =============================================================================
   The public knowledge pages: /tarot/karty, /tarot/karty/{slug}, /snar and
   /snar/{slug} (spec sec. 87–90).

   These are the pages a stranger arrives on from a search result, and they are
   judged in about a second against whatever else was on that result page. So
   they are built out of the plates and rules the rest of the site already uses
   rather than out of a "content" style of their own — five new blocks, and four
   of them exist because a catalogue needs to be navigable in ways a reading
   never did.
   ============================================================================= */

/* Breadcrumbs: Tarot → Karty → Věž.

   Hairline-small and muted, because a breadcrumb is orientation and not
   navigation — it answers "where am I" for somebody who arrived sideways, and
   it is the trail a search engine prints under the result. The separator is the
   system's diamond, drawn by CSS so it is never read aloud between every pair
   of words.

       <nav class="breadcrumbs" aria-label="Drobečková navigace">
         <ol class="breadcrumbs__list">
           <li class="breadcrumbs__item"><a href="…">Tarot</a></li>
           <li class="breadcrumbs__item" aria-current="page">Věž</li>
         </ol>
       </nav> */
.breadcrumbs {
    padding-block-start: var(--space-6);
}

.breadcrumbs__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    padding: 0;
    margin: 0;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    list-style: none;
}

.breadcrumbs__item {
    display: flex;
    gap: var(--space-3);
    align-items: center;
    color: var(--color-text-muted);
}

.breadcrumbs__item + .breadcrumbs__item::before {
    color: var(--color-gold-dim);
    content: '\25C6';
    font-size: 0.5em;
}

.breadcrumbs__item a {
    color: var(--color-text-secondary);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.breadcrumbs__item a:hover {
    color: var(--color-gold-bright);
}

/* A card plate that is a link — the index pages, where seventy-eight plates are
   seventy-eight destinations.

   The anchor *is* the plate rather than sitting inside it, so the whole
   engraving is the target and not the two words on it. The hover is the one the
   .card already uses (gold line, gold glow), so a plate and a card answer a
   pointer the same way. */
.card-plate--link {
    text-decoration: none;
    transition:
        border-color var(--transition-fast),
        box-shadow var(--transition-fast),
        transform var(--transition-fast);
}

.card-plate--link:hover,
.card-plate--link:focus-visible {
    border-color: var(--color-gold-dim);
    box-shadow: var(--shadow-sm), var(--glow-inset), var(--glow-gold);
    transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
    .card-plate--link:hover,
    .card-plate--link:focus-visible {
        transform: none;
    }
}

/* An index of many short names wants narrower plates than a spread of three:
   at 8.5rem a suit of fourteen wraps into rows of three on a laptop, which
   reads as a list rather than as a deck laid out. */
.card-row--index {
    gap: var(--space-3);
    grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
}

.card-row--index .card-plate {
    min-height: 8.5rem;
}

.card-row--index .card-plate__name {
    font-size: var(--text-lg);
}

/* The head of an entry page: the plate on the left, the short reading beside
   it. Deliberately the same two-column arrangement as .daily-card — one card
   introduced by one paragraph is the same problem twice — and a separate rule
   rather than a second selector on that one, because the karta dne is a lead
   magnet and this is a catalogue entry, and the two will not always want the
   same measurements. */
.entry-head {
    display: grid;
    gap: var(--space-6);
    align-items: start;
}

@media (min-width: 40rem) {
    .entry-head {
        grid-template-columns: 12rem 1fr;
    }
}

.entry-head__plate {
    min-height: 15rem;
}

/* The facts strip under a heading: „Velká arkána · číslo 16 · živel oheň".
   Runs inline, wraps on a phone, and is separated by the same diamond the
   breadcrumbs use. */
.entry-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    padding: 0;
    margin: 0;
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    list-style: none;
}

.entry-facts__item {
    display: flex;
    gap: var(--space-3);
    align-items: center;
}

.entry-facts__item + .entry-facts__item::before {
    color: var(--color-gold-dim);
    content: '\25C6';
    font-size: 0.5em;
}

/* =============================================================================
   Legal pages — /obchodni-podminky, /ochrana-osobnich-udaju, /kontakt (M12).

   Long documents nobody reads for pleasure and everybody reads under pressure:
   somebody wants to know whether they can cancel, or what happens to their
   data. So the type is set for scanning rather than for atmosphere — numbered
   headings that can be cited, a measure short enough to track across, and
   tables where the answer is genuinely tabular.

   Built out of the tokens like everything else; the only new colour here is the
   one on .todo-legal, which is deliberately loud.
   ============================================================================= */

.legal {
    --stack-space: var(--space-5);
}

.legal__meta {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
}

.legal__section {
    max-inline-size: 62ch;
    padding-block-start: var(--space-6);
    border-block-start: 1px solid var(--color-border);
}

.legal__section > * + * {
    margin-block-start: var(--space-4);
}

.legal__section h2 {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 600;
    line-height: var(--leading-snug);
    color: var(--color-text);
}

.legal__section h3 {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--color-text-secondary);
}

.legal__section p,
.legal__section li {
    line-height: var(--leading-relaxed);
    color: var(--color-text-secondary);
}

.legal__section ul {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding-inline-start: var(--space-5);
}

/* The operator's identity block and the like: a plate, so the details somebody
   came for are findable without reading the paragraph around them. */
.legal__party {
    padding: var(--space-5);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

.legal__party > * + * {
    margin-block-start: var(--space-3);
}

/* Wider than the prose it sits in — a three-column table squeezed to 62ch
   wraps every cell to two lines and stops being a table. */
.legal__table {
    inline-size: 100%;
    max-inline-size: none;
    font-size: var(--text-sm);
    border-collapse: collapse;
}

.legal__table th,
.legal__table td {
    padding: var(--space-3) var(--space-4);
    text-align: start;
    vertical-align: top;
    border-block-end: 1px solid var(--color-border);
}

.legal__table th {
    font-size: var(--text-2xs);
    font-weight: 600;
    color: var(--color-gold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    border-block-end-color: var(--color-gold-line);
}

.legal__table td {
    color: var(--color-text-secondary);
}

.legal__table tbody tr:last-child td {
    border-block-end: 0;
}

.legal__table code {
    color: var(--color-text);
}

/* The two sections that must not be skimmed past: the withdrawal clause and
   the entertainment disclaimer. Given the gilded ground the summary of a
   reading uses, which is the strongest "read this" the system has. */
.legal__section--highlight,
.legal__section--disclaimer {
    padding: var(--space-5);
    background-color: var(--color-gold-wash);
    border: 1px solid var(--color-gold-line);
    border-block-start-color: var(--color-gold-line);
    border-radius: var(--radius-sm);
}

/* The sentence spec sec. 130 fixes the wording of. Set in the display face at
   reading size so it carries as a statement rather than as fine print. */
.legal__disclaimer {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    line-height: var(--leading-relaxed);
    color: var(--color-text);
}

/* Unfilled legal detail. Loud on purpose — copper on ink, in the mono face,
   with a rule under it — because the failure this guards against is somebody
   skimming the page before launch and not noticing that the IČO is a bracket.
   LegalPlaceholdersArePendingTest is the other half of the same guard. */
.todo-legal {
    padding: 0.1em 0.4em;
    font-family: var(--font-mono);
    font-size: 0.9em;
    color: var(--color-text-inverse);
    background-color: var(--color-warning);
    border-radius: var(--radius-xs);
}

/* =============================================================================
   The § 1837 notice by a payment button, and the standing disclaimer in the
   footer. Both are fine print in the literal sense: present, legible, and not
   competing with the thing they qualify.
   ============================================================================= */

.digital-consent {
    max-inline-size: 46ch;
    margin-block-start: var(--space-3);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--color-text-muted);
}

.site-footer__disclaimer {
    margin-block-start: var(--space-5);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--color-text-muted);
}

/* =============================================================================
   Cookie notice — a statement, not a consent dialog. See
   assets/controllers/cookie_notice_controller.js for why there is no choice to
   offer.

   Because it is not a dialog it does not behave like one: no overlay, no focus
   trap, nothing blocked underneath. It sits at the bottom of the viewport,
   sized by its one sentence, and goes away for good when dismissed.
   ============================================================================= */

.cookie-notice {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 60;
    padding-block: var(--space-3);
    background-color: rgb(6 8 15 / 94%);
    border-block-start: 1px solid var(--color-gold-line);
    backdrop-filter: blur(14px) saturate(140%);
}

.cookie-notice__inner {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
    align-items: center;
    justify-content: space-between;
}

.cookie-notice__text {
    font-size: var(--text-sm);
    color: var(--color-text-secondary);
}

.cookie-notice__button {
    flex: none;
}

/* The bar is fixed, so at the very bottom of a page it would sit on top of the
   footer — which is where the legal links and the disclaimer live, i.e. exactly
   what somebody following „Co to znamená" is scrolling towards.

   :has() rather than a class the controller toggles, so the reservation appears
   and disappears with the bar itself and there is no state to keep in step. It
   is also correctly absent for the visitor who has already dismissed it: the
   controller leaves the element `hidden`, the selector does not match, and no
   dead space is left behind. Browsers without :has() simply get the overlap
   they would have got anyway. */
body:has(.cookie-notice:not([hidden])) {
    padding-block-end: 5rem;
}
