    /* ── Zprávy ─── */
    /* No bottom padding: both columns own scrollers that must reach the
       viewport edge, otherwise the brief and the feed are clipped mid-line by
       the area's overflow. The breathing room lives inside the scrollers. */
    /* No right gutter on the page: the feed is the rightmost column and its
       scroller has to reach the window edge, so the thumb rides the edge of the
       screen instead of floating in the margin beside the cards. The gutter is
       not lost -- it moves inside the scroller, where it insets the content and
       leaves the scrollbar outside it. */
    .zpravy-area { flex: 1; overflow: hidden; padding: var(--main-pad) 0 0 calc(var(--rail-width) + var(--main-pad)); display: none; }

    /* ── Datové zdroje ─── */
    .datasources-area { flex: 1; overflow: hidden; display: none; }
    .datasources-wrap { width: 100%; max-width: none; margin: 0; }
    .datasources-wrap {
      min-height: 0;
      display: flex;
      flex-direction: column;
    }
    .ds-upload-btn {
      padding: 0;
      font-weight: 500;
      font-size: 14px;
      cursor: pointer;
      transition: background .15s, border-color .15s, color .15s, transform .15s;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex: 0 0 auto;
      margin-left: auto;
    }    .ds-upload-btn svg {
      width: 18px;
      height: 18px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.9;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .ds-filter {
      width: 100%;
      min-width: 0; outline: none; box-sizing: border-box;
    }
    .ds-filter:focus {
      box-shadow: none;
    }
    .library-filter:focus {
      border-color: var(--border-input);
      box-shadow: none;
    }
    .library-filter::selection,
    .ds-filter::selection,
    .chat-history-rename::selection {
      background: rgba(15, 23, 42, 0.14);
      color: inherit;
    }
    .ds-type-dd { position: relative; flex: 0 0 auto; }
    .datasources-sidebar {
      min-height: 0;
      display: flex;
      flex-direction: column;
      gap: 0;
      overflow: hidden;
    }
    .datasources-sidebar-controls {
      display: flex;
      flex-direction: column;
      border-radius: 0;
    }
    .ds-type-dd-btn {
	      display: flex;
	      align-items: center;
	      gap: 3px;
	      height: 100%;
	      border: 0;
      cursor: pointer;
      transition: background .15s, color .15s;
    }.ds-type-dd-icon { display: inline-flex; width: 16px; height: 16px; flex: 0 0 auto; }
    .ds-type-dd-icon svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
    .ds-type-dd-chev { width: 11px; height: 11px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
    .ds-type-menu {
      /* position: fixed (not absolute) + JS-computed top/left in app.js --
         .datasources-sidebar clips overflow for its rounded corners, which
         would otherwise cut this popover off. */
      position: fixed;
      z-index: 60;
      display: none;
      border: 1px solid var(--border);
      border-radius: var(--r-lg);
      background: var(--surface);
      box-shadow: var(--shadow-pop);
      padding: 4px;
      min-width: 172px;
    }
    .ds-type-menu.open { display: block; }
    .ds-type-menu-item {
      display: flex;
      align-items: center;
      gap: 8px;
      width: 100%;
      border: 0;
      background: transparent;
      text-align: left;
      padding: 7px 9px;
      border-radius: 8px;
      cursor: pointer;
    }.ds-type-menu-item svg {
      width: 14px;
      height: 14px;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.8;
      stroke-linecap: round;
      stroke-linejoin: round;
      opacity: .8;
      flex: 0 0 auto;
    }
    .datasources-body {
      flex: 1;
      min-height: 0;
      display: grid;
    }
	    .ds-list {
	      display: flex;
	      flex-direction: column;
	      height: 100%;
	      overflow-y: auto;
	      min-width: 0;
	    }
	    .ds-item {
	      cursor: pointer;
	      transition: background .15s, color .15s, border-color .15s;
	      position: relative;
	      display: flex;
	      align-items: center;
	    }
	    .ds-item:last-child {
	      border-bottom: 0;
	    }.ds-item-name {
	      min-width: 0;
	      margin: 0;
	      letter-spacing: -0.01em;
	      overflow: hidden;
	      display: -webkit-box;
	      -webkit-line-clamp: 2;
	      -webkit-box-orient: vertical;
	    }
    .ds-badge {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 24px;
      height: 24px;
      border: 0;
      border-radius: 0;
      background: transparent;
      opacity: .9;
    }
    .ds-badge:focus-visible {
      outline: 2px solid rgba(15, 23, 42, 0.18);
      outline-offset: 2px;
      border-radius: 6px;
    }
    .ds-badge svg {
      width: 21px;
      height: 21px;
      display: block;
      stroke: currentColor;
      fill: none;
      stroke-width: 1.9;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .eurostat-mark {
      display: inline-grid;
      place-items: center;
      width: 18px;
      height: 18px;
      flex: 0 0 auto;
      border: 1.5px solid currentColor;
      border-radius: 5px;
      color: currentColor;
      font-family: var(--font-sans);
      font-size: 8px;
      font-weight: 700;
      line-height: 1;
      letter-spacing: -.04em;
    }

    .ds-type-dd-icon .eurostat-mark {
      width: 16px;
      height: 16px;
      border-radius: 4.5px;
      font-size: 7px;
    }

    .ds-type-menu-item .eurostat-mark {
      width: 14px;
      height: 14px;
      border-width: 1.4px;
      border-radius: 4px;
      font-size: 6px;
    }
    .ds-badge.xlsx,
    .ds-badge.sql,
    .ds-badge.eurostat,
    .ds-badge.cnb,
    .ds-badge.csu {
      color: var(--ink);
    }
    .answer-inspector-content[data-view="resources"] .data-source-card {
      border: 0;
      border-radius: 0;
      background: transparent;
    }

    .answer-inspector-content[data-view="resources"] .data-source-card + .data-source-card {
      border-top: 1px solid var(--border-soft);
    }

    .ds-detail-type-icon {
      flex: 0 0 auto;
      opacity: .82;
      margin-right: -2px;
    }
    .ds-detail {
      display: flex; flex-direction: column;
      padding: 0; min-height: 0; height: 100%; min-width: 0; overflow: visible;
    }    .ds-detail-empty { color: var(--muted); text-align: center; padding: 60px 20px; font-size: 14px; }
    .ds-detail > .ds-detail-empty {
      margin: auto;
      padding: 0 20px;
    }
    .ds-detail-empty.loading {
      color: var(--faint);
      display: flex;
      align-items: center;
      justify-content: center;
      min-height: 140px;
    }
    .ds-detail-header {
      justify-content: space-between;
      margin-bottom: 0;
      flex: 0 0 auto;
      overflow: visible;
    }
    .ds-detail-heading {
      min-width: 0;
      flex: 1 1 auto;
      overflow: visible;
    }
    .ds-detail-heading > div:first-child { min-width: 0; }
    .ds-detail-title-row {
      min-width: 0;
      display: inline-flex;
      align-items: center;
      flex: 1 1 auto;
    }
    .ds-detail-name {
      margin: 0;
      min-width: 0;
    }.ds-btn {
      padding: 6px 14px; border-radius: var(--r-sm); border: 1px solid var(--text); font-size: 13px; cursor: pointer;
      transition: background var(--dur), border-color var(--dur);
    }    .ds-btn:disabled { opacity: .45; cursor: not-allowed; }
    .ds-btn:disabled:hover { background: #1f2937; border-color: var(--text); }
    .ds-btn.primary { background: var(--green); color: #0a0a0a; border-color: var(--green); font-weight: 600; }
    .ds-btn.primary:hover { background: var(--green); border-color: var(--green); }
    .ds-btn.danger { color: var(--red); border-color: var(--red); }
    .ds-btn.danger:hover { background: #7f1d1d; color: var(--surface); }.ds-btn.compact {
      padding: 7px 11px;
      border-radius: 999px;
      font-size: 12px;
    }
    .ds-detail-tabs {
      display: inline-flex;
      align-items: center;
      padding: 0;
      border-radius: 10px;
      border: 0;
      width: fit-content;
      white-space: nowrap;
    }
    .ds-detail-tab {
      border: none;
      background: transparent;
      letter-spacing: 0;
      cursor: pointer;
      transition: background .15s, color .15s;
    }.ds-detail-content {
      flex: 1 1 auto;
      min-height: 0;
      overflow: auto;
      display: flex;
      flex-direction: column;
    }
    .ds-detail-panel {
      display: none;
    }
    .ds-detail-panel.active {
      display: block;
      flex: 1 1 auto;
      min-height: 0;
    }
    .ds-technical-grid {
      align-items: stretch;
    }
    .ds-technical-field {
      grid-template-columns: minmax(180px, 240px) minmax(0, 1fr);
      min-width: 0;
    }
    .ds-technical-input {
      width: 100%;
      min-width: 0;
      box-sizing: border-box;
      border-radius: 12px;
      border: 1px solid var(--border);
      background: var(--accent);
      color: #e5e7eb;
      font: inherit;
      outline: none;
      transition: border-color .15s, box-shadow .15s, background .15s;
    }

    .ds-technical-input:focus {
      border-color: var(--green);
      box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.12);
    }
    .ds-detail-panel[data-detail-panel="description"].active {
      display: flex;
      flex: 1 1 auto;
      min-height: 0;
    }
    .ds-detail-panel[data-detail-panel="preview"].active {
      display: flex;
      flex: 1 1 auto;
      flex-direction: column;
      min-height: 0;
      margin: -16px -20px -20px;
    }
    .ds-detail-desc {
      width: 100%; border-radius: 8px;
      border: 1px solid var(--border); background: #0b1220; color: var(--border-card-hover);
      font-family: inherit; outline: none; box-sizing: border-box;
    }
    .ds-detail-desc:focus { border-color: #22c55e; }
    .ds-detail-section-title {
      font-size: 14px;
      font-weight: 500;
      margin: 0 0 8px 0;
      text-transform: none;
      letter-spacing: 0;
    }    .ds-description-layout {
      flex: 1 1 auto;
      align-items: stretch;
      margin-top: 0;
      min-height: 0;
      width: 100%;
    }
    .ds-description-rules {
      grid-column: 1 / -1;
    }
    .ds-description-row-meaning {
      grid-column: 1 / -1;
    }    .ds-description-rules .ds-detail-desc {
      flex: 1 1 auto;
    }
    .ds-detail-desc-field {
      min-width: 0;
      display: flex;
      flex-direction: column;
    }.ds-schema-relations,
    .ds-relation-pairs {
	      display: flex;
	      flex-direction: column;
	      gap: 0;
	    }
    .ds-schema-relations {
      gap: 14px;
    }
    .ds-schema-table-wrap {
      border: 1px solid #1f2937;
      border-radius: 10px;
      overflow: hidden;
    }
    table.ds-schema-table {
      border-collapse: collapse;
      width: 100%;
      table-layout: fixed;
    }
    table.ds-schema-table th {
      text-align: left;
      padding: 8px 12px;
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: .06em;
      text-transform: uppercase;
      border-bottom: 1px solid #1f2937;
    }
    table.ds-schema-table td {
      padding: 7px 12px;
      border-bottom: 1px solid #1f2937;
      vertical-align: top;
    }
    table.ds-schema-table tr:last-child td {
      border-bottom: 0;
    }    .ds-schema-table col.col-name { width: 17%; }
    .ds-schema-table col.col-type { width: 16%; }
    .ds-schema-table col.col-unit { width: 12%; }
    .ds-schema-name-cell {
      font-weight: 650;
      overflow-wrap: anywhere;
    }
    .ds-schema-type-cell {
      overflow-wrap: anywhere;
    }
    .ds-relation-source,
    .ds-relation-local,
    .ds-relation-target,
    .ds-relation-picker-input {
      width: 100%;
      min-width: 0;
      border: 1px solid var(--border);
      background: var(--accent);
      color: #d1d5db;
      border-radius: 8px;
      padding: 9px 10px;
      font-size: 13px;
      outline: none;
      box-sizing: border-box;
    }
    .ds-relation-description {
      width: 100%;
      min-height: 64px;
      border: 1px solid var(--border);
      background: var(--accent);
      color: #d1d5db;
      border-radius: 8px;
      resize: none;
      outline: none;
      box-sizing: border-box;
      font-family: inherit;
      min-height: 58px;
    }
    .ds-column-description {
      width: 100%;
      min-height: 34px;
      height: auto;
      max-height: none;
      border: 1px solid transparent;
      background: transparent;
      color: #d1d5db;
      border-radius: 6px;
      padding: 6px 8px;
      font-size: 12.5px;
      line-height: 1.4;
      resize: none;
      overflow: visible;
      field-sizing: content;
      outline: none;
      box-sizing: border-box;
      font-family: inherit;
    }
    .ds-column-description:hover {
      background: rgba(148, 163, 184, 0.08);
    }
    .ds-column-unit {
      width: 100%;
      min-width: 0;
      border: 1px solid transparent;
      background: transparent;
      color: #d1d5db;
      border-radius: 6px;
      padding: 6px 8px;
      font-size: 12.5px;
      outline: none;
      box-sizing: border-box;
    }
    .ds-column-unit:hover {
      background: rgba(148, 163, 184, 0.08);
    }
    .ds-relation-head,
    .ds-relation-pair {
      display: grid;
      grid-template-columns: minmax(140px, 1fr);
      gap: 8px;
      align-items: center;
    }
    .ds-relation-pair {
      grid-template-columns: minmax(130px, 1fr) auto minmax(130px, 1fr);
    }
    .ds-relation-head {
      padding-right: 0;
    }
    .ds-relation-card {
      position: relative;
      display: flex;
      flex-direction: column;
      min-width: 0;
      transition: border-color .15s, background .15s, box-shadow .15s, transform .15s;
      overflow: hidden;
    }.ds-relation-list {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 430px), 1fr));
      align-items: start;
    }
    .ds-relation-add-card {
      border: 1px dashed var(--border);
      background: transparent;
      cursor: pointer;
      display: grid;
      place-items: center;
      font: inherit;
      transition: border-color .15s, background .15s, color .15s;
    }    .ds-relation-remove {
      position: absolute;
      top: 0;
      right: 0;
      width: 28px;
      height: 28px;
      padding: 0;
      border: 0;
      border-radius: 0 14px 0 12px;
      background: transparent;
      opacity: 0;
      pointer-events: none;
      display: inline-grid;
      place-items: center;
      font-size: 0;
      line-height: 1;
      transition: opacity .14s, background .14s, color .14s, transform .14s;
    }
    .ds-relation-card:hover .ds-relation-remove,
    .ds-relation-card:focus-within .ds-relation-remove {
      opacity: 1;
      pointer-events: auto;
    }
    .ds-relation-remove::before {
      content: "";
      width: 15px;
      height: 15px;
      display: block;
      background: currentColor;
      -webkit-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 7h16'/%3E%3Cpath d='M10 11v6'/%3E%3Cpath d='M14 11v6'/%3E%3Cpath d='M6 7l1 14h10l1-14'/%3E%3Cpath d='M9 7V4h6v3'/%3E%3C/svg%3E") center / contain no-repeat;
      mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 7h16'/%3E%3Cpath d='M10 11v6'/%3E%3Cpath d='M14 11v6'/%3E%3Cpath d='M6 7l1 14h10l1-14'/%3E%3Cpath d='M9 7V4h6v3'/%3E%3C/svg%3E") center / contain no-repeat;
    }    .ds-relation-picker-overlay {
      position: fixed;
      inset: 0;
      z-index: 220;
      display: none;
      align-items: center;
      justify-content: center;
      padding: 18px;
      background: rgba(2, 6, 23, 0.68);
    }
    .ds-relation-picker-overlay.open {
      display: flex;
    }
    .ds-relation-picker-modal {
      width: min(92vw, 640px);
      max-height: min(78vh, 680px);
      border: 1px solid #263449;
      border-radius: 16px;
      padding: 18px;
      display: flex;
      flex-direction: column;
      gap: 14px;
    }
    .ds-relation-picker-combobox {
      position: relative;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    .ds-relation-picker-input:focus {
      border-color: var(--border-focus);
    }
    .ds-relation-picker-list {
      height: min(44vh, 420px);
      min-height: 280px;
      overflow-y: auto;
      border: 1px solid #263449;
      border-radius: 14px;
      padding: 8px;
      display: flex;
      flex-direction: column;
      gap: 6px;
    }
    .ds-relation-picker-option {
      width: 100%;
      border: 1px solid #1f2d42;
      border-radius: 11px;
      padding: 12px 13px;
      text-align: left;
      cursor: pointer;
      transition: background .15s, border-color .15s, color .15s, transform .15s;
    }
    .ds-relation-picker-option:hover,
    .ds-relation-picker-option.active {
      background: rgba(34, 197, 94, 0.12);
      border-color: rgba(34, 197, 94, 0.45);
      color: #dcfce7;
      transform: translateY(-1px);
    }
    .ds-relation-picker-option-name {
      font-size: 14px;
      font-weight: 700;
      line-height: 1.35;
    }
    .ds-relation-picker-head,
    .ds-relation-picker-actions {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
    }
    .ds-relation-picker-title {
      font-size: 14px;
      font-weight: 800;
    }
    .ds-relation-picker-close {
      border: 1px solid var(--border);
      border-radius: 8px;
      width: 32px;
      height: 32px;
      cursor: pointer;
    }
    .ds-relation-picker-empty {
      font-size: 13px;
      min-height: 18px;
    }    table.ds-schema-table th {
      background: var(--surface-inset);
      color: var(--muted);
    }    table.ds-schema-table tr:hover td {
      background: var(--surface-inset);
    }
    .ds-relation-card {
      border-color: var(--border-input);
      color: var(--ink);
    }.ds-relation-remove {
      color: var(--muted);
      box-shadow: none;
    }
    .ds-relation-remove:hover {
      background: rgba(226, 232, 240, 0.72);
      color: var(--ink);
    }
    .datasources-sidebar {
      border-color: var(--border);
      box-shadow: 0 14px 34px rgba(15, 23, 42, 0.05);
    }
    .datasources-sidebar-controls {
      border-color: var(--border);
    }.ds-relation-source,
    .ds-relation-local,
    .ds-relation-target,
    .ds-column-unit,
    .ds-relation-picker-input,
    .ds-column-description,
    .ds-relation-description {
      background: var(--surface);
      color: var(--ink);
      border-color: var(--border-card-hover);
    }
    .ds-relation-picker-list {
      background: var(--surface-inset);
      border-color: var(--border-input);
    }
    .ds-relation-picker-option {
      background: var(--surface);
      border-color: var(--border);
      color: var(--ink);
    }
    .ds-relation-picker-option:hover {
      background: var(--hover-bg);
      border-color: var(--border-card-hover);
      color: var(--ink);
    }
    .ds-relation-picker-option.active {
      background: var(--active-bg);
      border-color: var(--border-card-hover);
      color: var(--ink);
    }
    .ds-relation-picker-modal {
      background: var(--surface);
      border-color: var(--border-input);
      box-shadow: 0 24px 70px rgba(15, 23, 42, 0.18);
    }
    .ds-relation-picker-title {
      color: var(--ink);
    }
    .ds-relation-picker-close {
      background: var(--surface-inset);
      color: var(--text);
      border-color: var(--border-card-hover);
    }
    .ds-relation-picker-empty {
      color: var(--muted);
    }
    @media (max-width: 900px) {
      .ds-schema-workspace,
    .ds-description-layout,
    .ds-technical-grid,
    .ds-technical-field,
    .ds-relation-pair {
        grid-template-columns: 1fr;
      }
      .ds-description-rules {
        grid-column: auto;
      }
      .ds-description-row-meaning {
        grid-column: auto;
      }
      .ds-detail-panel[data-detail-panel="description"].active {
        min-height: 0;
      }
      .ds-description-layout {
        grid-template-rows: none;
      }
      .ds-relation-pair span {
        display: none;
      }
    }.ds-detail-header {
      border-bottom-color: var(--border);
    }
    .ds-btn {
      background: var(--surface-page);
      color: var(--text);
      border-color: var(--border-card-hover);
    }
    .ds-btn:hover {
      background: var(--active-bg);
      border-color: var(--border-focus);
    }
    .ds-btn.ghost {
      background: var(--surface);
      color: var(--text);
      border-color: var(--border-card-hover);
    }
    .ds-btn.ghost:hover {
      background: var(--hover-bg);
      border-color: var(--border-focus);
    }
    .ds-detail-tabs {
      background: transparent;
    }.ds-detail-heading {
      grid-template-columns: minmax(0, 1fr) max-content;
    }
    .ds-detail-title-row {
      align-self: start;
      overflow: visible;
    }
    .ds-detail-name {
      max-width: 100%;
      white-space: normal;
      overflow-wrap: anywhere;
      word-break: normal;
    }
    .ds-detail-tabs {
      align-self: start;
      justify-self: end;
      flex-wrap: wrap;
      justify-content: flex-end;
      row-gap: 4px;
      max-width: min(100%, 420px);
    }
    .ds-detail-desc,
    .ds-technical-input,
    .ds-related-source,
    .ds-related-reason {
      background: var(--surface);
      color: var(--ink);
      border-color: var(--border-card-hover);
    }.ds-detail-desc-field .ds-detail-section-title { margin: 0 0 8px 0; }#ds-sheet-preview {
      flex: 1 1 auto;
      min-height: 0;
      display: flex;
      flex-direction: column;
    }
    .ds-sheet { border: 1px solid #1f2937; border-radius: 8px; margin-bottom: 12px; overflow: hidden; }
    #ds-sheet-preview .ds-sheet {
      flex: 1 1 auto;
      min-height: 0;
      display: flex;
      flex-direction: column;
      margin-bottom: 0;
      border: 0;
      border-radius: 0;
      background: transparent;
    }
    .ds-sheet-table-wrap { overflow: auto; max-height: 460px; }
    #ds-sheet-preview .ds-sheet-table-wrap {
      flex: 1 1 auto;
      max-height: none;
      min-height: 0;
      background: var(--surface-inset);
    }
    .ds-sheet-table { width: 100%; border-collapse: collapse; }
    .ds-sheet-table th { text-align: left; white-space: nowrap; }
    .ds-sheet-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }@media (max-width: 1180px) {}

    /* ── Excel catalogue wizard ─── */
    .ds-upload-overlay { display: none; position: fixed; inset: 0; z-index: 1000; align-items: center; justify-content: center; background: rgba(15,23,42,.36); }
    .ds-upload-overlay.open { display: flex; }
    .ds-upload-modal { width: min(1180px, 96vw); height: min(820px, 92vh); display: flex; flex-direction: column; overflow: hidden; background: var(--surface); border: 1px solid var(--border); border-radius: 18px; box-shadow: 0 24px 70px rgba(15,23,42,.18); }
    .ds-upload-header { min-height: 58px; display: flex; align-items: center; justify-content: space-between; padding: 0 22px; border-bottom: 1px solid #e3e9f0; }
    .ds-upload-title { color: var(--ink); font-size: 17px; font-weight: 650; }
    .ds-upload-close { width: 32px; height: 32px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted); font-size: 24px; cursor: pointer; }
    .ds-upload-close:hover { background: var(--hover-bg); color: var(--ink); }
    .ds-upload-body { min-height: 0; flex: 1; display: flex; padding: 0; overflow: hidden; }
    .ds-upload-step { min-height: 0; flex: 1; }
    .ds-upload-step[hidden] { display: none !important; }
    #ds-upload-step1 { display: grid; place-items: center; padding: 34px; }
    .ds-upload-start { width: min(620px, 100%); display: flex; flex-direction: column; gap: 14px; }
    .ds-upload-dropzone { padding: 54px 24px; border: 1px dashed #b9c8d9; border-radius: 14px; text-align: center; cursor: pointer; transition: background .15s, border-color .15s; }
    .ds-upload-dropzone:hover,
    .ds-upload-dropzone.drag { border-color: var(--green); background: var(--border-soft); }
    .ds-upload-icon { width: 34px; height: 34px; display: inline-grid; place-items: center; margin-bottom: 12px; color: #172033; }
    .ds-upload-icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.6; }
    .ds-upload-hint { color: var(--text); font-size: 14px; }
    .ds-upload-hint small { display: block; margin-top: 5px; color: #8491a3; }
    .ds-upload-filename { min-height: 18px; margin-top: 10px; color: var(--ink); font-size: 13px; font-weight: 600; }
    .ds-upload-submit,
    .ds-upload-save { border: 1px solid var(--border); border-radius: 9px; background: var(--border); color: var(--surface); font-weight: 600; cursor: pointer; }
    .ds-upload-submit { min-width: 154px; align-self: center; padding: 10px 24px; }
    .ds-upload-submit:disabled,
    .ds-upload-save:disabled { opacity: .65; cursor: default; }
    .ds-upload-status { min-height: 18px; color: var(--muted); font-size: 12px; text-align: center; }
    #ds-upload-step2 { display: flex; flex-direction: column; width: 100%; }
    .ds-upload-progress { height: 3px; background: #edf1f5; }
    .ds-upload-progress span { display: block; height: 100%; width: 0; background: var(--ink); transition: width .25s ease; }
    .ds-upload-wizard { min-height: 0; flex: 1; display: flex; }
    .ds-upload-input,
    .ds-upload-description { box-sizing: border-box; width: 100%; border: 1px solid #d5dfeb; border-radius: 9px; background: var(--surface); color: #172033; outline: none; font: inherit; }
    .ds-upload-input { min-height: 38px; padding: 8px 11px; }
    .ds-upload-description { min-height: 104px; padding: 10px 11px; resize: none; line-height: 1.5; }
    .ds-upload-input:focus,
    .ds-upload-description:focus { border-color: #9eacbc; }
    .ds-upload-desccol { min-width: 0; min-height: 0; flex: 1; display: flex; flex-direction: column; padding: 22px; }
    .ds-upload-editor-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid #e6ebf1; }
    .ds-upload-editor-head h3 { margin: 0 0 5px; color: var(--ink); font-size: 17px; line-height: 1.25; }
    .ds-upload-editor-head p { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.45; }
    .ds-upload-sheet-progress { margin-top: 2px; color: var(--muted); font-size: 12px; white-space: nowrap; }
    .ds-upload-sheets { min-height: 0; flex: 1; overflow: auto; padding-right: 4px; }
    .ds-upload-field { display: grid; gap: 6px; margin-bottom: 15px; }
    .ds-upload-fieldrow { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
    .ds-upload-label { color: var(--text); font-size: 12px; font-weight: 600; }
    .ds-upload-sheet-choice { display: grid; grid-template-columns: auto minmax(0,1fr); align-items: center; gap: 12px; padding: 13px 4px; border-bottom: 1px solid #e5ebf2; }
    .ds-upload-sheet-choice strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
    .ds-upload-sheet-choice small { color: var(--muted); }
    .ds-upload-sheet-choice input { accent-color: var(--ink); }
    .ds-upload-list-section { margin-top: 8px; padding-top: 16px; border-top: 1px solid #e6ebf1; }
    .ds-upload-list-section > .ds-upload-label { display: block; margin-bottom: 4px; }
    .ds-upload-column { display: grid; grid-template-columns: minmax(120px,.55fr) minmax(0,1.45fr) 110px; gap: 10px; align-items: start; padding: 11px 0; border-bottom: 1px solid #e7edf3; }
    .ds-upload-column-name { padding-top: 9px; font: 600 12px ui-monospace, SFMono-Regular, monospace; overflow-wrap: anywhere; }.ds-upload-preview { margin-top: 16px; max-height: 260px; overflow: auto; border: 1px solid #dce5ef; border-radius: 10px; }
    .ds-upload-preview table { width: max-content; min-width: 100%; border-collapse: collapse; font-size: 11px; }
    .ds-upload-preview th,
    .ds-upload-preview td { padding: 7px 9px; border-bottom: 1px solid #e5ebf2; text-align: left; white-space: nowrap; }
    .ds-upload-preview th { background: var(--hover-bg); color: #253247; font-weight: 650; }
    .ds-upload-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 13px 22px; border-top: 1px solid #e3e9f0; }
    .ds-upload-actions-right { display: flex; align-items: center; gap: 9px; }
    .ds-upload-save { min-width: 112px; padding: 9px 16px; }
    .ds-upload-action-loader { display: inline-block; width: 14px; height: 14px; margin: 0 auto; border: 2px solid rgba(255,255,255,.36); border-top-color: var(--surface); border-radius: 50%; animation: spin .75s linear infinite; vertical-align: middle; }
    .ds-upload-cancel { padding: 8px 10px; border: 0; background: transparent; color: var(--muted); cursor: pointer; }
    .ds-upload-cancel:hover { color: #b42318; }
    #ds-upload-savestatus { margin: 0 auto 0 0; text-align: left; }
    @media (max-width: 760px) {
      .ds-upload-modal { width: 100vw; height: 100dvh; max-height: none; border-radius: 0; }
      .ds-upload-desccol { padding: 18px 14px; }
      .ds-upload-column { grid-template-columns: 1fr; }
    }

    @media (max-width: 1100px) {
      .datasources-area { padding: var(--main-pad) var(--main-pad) var(--main-pad) calc(var(--rail-width) + var(--main-pad)); }
      .datasources-wrap { height: auto; }
      .datasources-body { grid-template-columns: 1fr; }
      .ds-list { max-height: 260px; height: auto; }
      .ds-detail { height: auto; min-height: 320px; }
    }.zpravy-wrap {
      width: 100%;
      height: 100%;
      min-height: 0;
    }
    .zpravy-layout {
      display: grid;
      gap: 20px;
      height: 100%;
      min-height: 0;
    }
    .zpravy-main {
      min-height: 0;
      height: 100%;
      display: flex;
      flex-direction: column;
    }
    .zpravy-side {
      top: 0;
      display: flex;
      flex-direction: column;
    }
    .zpravy-side-controls {
      flex-direction: column;
    }

    .zpravy-upload-btn {
      border-radius: var(--r-sm);
      border: 1px solid rgba(34, 197, 94, 0.42);
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      transition: background .15s, border-color .15s, color .15s;
    }    .zpravy-scroll {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      /* The page gutter, carried here so the cards keep their inset while the
         scrollbar -- which sits outside the padding box -- reaches the edge. */
      padding-right: var(--main-pad);
      padding-bottom: var(--main-pad);
      overscroll-behavior: contain;
    }@keyframes zpravyDigestFade {
      0% { opacity: 0; transform: translateY(6px); }
      100% { opacity: 1; transform: translateY(0); }
    }.quiet-loader {
      width: 28px;
      height: 28px;
      border-radius: 999px;
      border: 2px solid rgba(100, 116, 139, 0.18);
      border-top-color: rgba(15, 23, 42, 0.62);
      animation: spin .75s linear infinite;
    }
    .zpravy-feed { display: flex; flex-direction: column; gap: 12px; }
    .zpravy-day-group {
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    .zpravy-article {
      border: 1px solid #1f2937;
      background: var(--ink);
      border-radius: 10px;
      overflow: hidden;
      padding: 14px 16px;
      display: flex;
      gap: 12px;
      align-items: flex-start;
      transition: border-color .15s;
    }    .zpravy-article.has-link { cursor: pointer; }
    .zpravy-article.has-link:focus-visible {
      outline: 2px solid var(--green);
      outline-offset: 2px;
    }
    .zpravy-article-image {
      width: 132px;
      height: 92px;
      flex: 0 0 auto;
      overflow: hidden;
      border-radius: 7px;
      background: var(--surface-inset);
    }
    .zpravy-article-image img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    .zpravy-article-info { flex: 1; min-width: 0; }
    .zpravy-article-title {
      font-size: 14px;
      font-weight: 500;
      color: #e5e7eb;
      margin-bottom: 4px;
    }
    .zpravy-article-summary {
      font-size: 13px;
      line-height: 1.6;
      color: var(--faint);
      margin-bottom: 6px;
      display: block;
      max-height: 4.8em;
      overflow: hidden;
    }
    .source-picker-item-text { min-width: 0; display: block; }
    .source-picker-item-name {
      color: inherit;
      display: block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }    .pending-live-steps-host { width: 100%; max-width: var(--content-width); margin: 0 auto; }
    .loading-steps { display: block; min-width: 0; width: 100%; }
    .loading-step-row { width: 100%; padding: 14px 0; font-size: 13px; line-height: 1.45; opacity: .92; animation: loadingTextPulse 1.25s ease-in-out infinite; margin-bottom: 8px; }
    .loading-step-row.done { animation: none; opacity: .9; }    .loading-step-title { font-size: 13px; font-weight: 600; margin-bottom: 6px; white-space: pre-wrap; overflow: visible; overflow-wrap: anywhere; max-width: 100%; min-width: 0; }
    .loading-step-title.tool-stream-reveal { animation: loadingToolStreamReveal .32s var(--ease-out) both; }
    @keyframes loadingTextPulse {
      0%, 100% { opacity: 1; }
      50% { opacity: .48; }
    }
    @keyframes loadingToolStreamReveal {
      from { clip-path: inset(0 100% 0 0); }
      to { clip-path: inset(0 0 0 0); }
    }
    @media (prefers-reduced-motion: reduce) {
      .loading-step-title.tool-stream-reveal { animation: none; }
    }
    .zpravy-article-meta {
      font-size: 12px;
      color: var(--muted);
      display: flex;
      gap: 12px;
      flex-wrap: wrap;
    }
    .zpravy-article-source {
      color: var(--green);
      font-weight: 600;
    }
    .zpravy-empty {
      border: 0;
      border-radius: 0;
      padding: 22px 0;
      background: transparent;
      color: var(--muted);
      font-size: 14px;
      text-align: center;
    }

    /* ── Light application palette ─────────── */
    body {
      background: var(--surface-page);
      color: var(--ink);
    }

    /* The page ground shows through. Warm white is for the things you act on
       -- the composer, cards, panels -- so the chat itself sits on flax and
       those surfaces read as raised off it. */
    #chat-area {
      background: transparent;
    }

    body.answer-inspector-open #chat-area {
      padding-right: calc(var(--answer-inspector-width) + var(--main-pad));
    }

    body.answer-inspector-open #input-area {
      right: var(--answer-inspector-width);
    }

    .left-rail {
      background: var(--surface-rail);
      border-right-color: var(--border);
      box-shadow: none;
    }

    .brand-title,
    .zpravy-title,
    .upload-section-title,
    .upload-modal-title,
    .ds-detail-name,
    .ds-upload-title,
    .zpravy-article-title {
      color: var(--ink);
    }

    .ds-sheet {
      background: var(--surface);
      border-color: var(--border);
    }

    .answer-feedback button:hover,
    .answer-retry:hover {
      color: var(--ink-strong);
    }

    .mode-btn {
      color: var(--ink);
    }

    .mode-btn:hover {
      background: var(--active-bg);
      color: var(--ink);
    }

    .mode-btn.active {
      background: var(--active-bg);
      color: var(--ink);
      box-shadow: none;
    }

    .mode-btn-icon {
      opacity: 1;
    }

    .chat-history-rail {
      border-top-color: transparent;
    }

    .chat-history-title,
    .chat-history-empty,
    .chat-history-loading,
    .chat-history-error {
      color: var(--muted);
    }

    .chat-history-main,
    .chat-history-name {
      color: var(--ink);
    }

    .chat-history-name {
      font-size: 14px;
    }

    .chat-history-main:hover {
      background: var(--active-bg);
      color: var(--ink);
    }

    .chat-history-item:hover .chat-history-main {
      background: var(--active-bg);
      color: var(--ink);
    }

    .chat-history-item.active .chat-history-main {
      background: var(--active-bg);
      color: var(--ink);
      box-shadow: none;
    }

    .chat-history-item.pending .chat-history-main,
    .chat-history-item.pending:hover .chat-history-main {
      background: transparent;
    }

    .chat-history-item.pending.active .chat-history-main,
    .chat-history-item.pending.active:hover .chat-history-main {
      background: var(--active-bg);
    }

    .loading-step-row {
      color: var(--text);
    }    .loading-step-title {
      color: var(--ink-strong);
    }
    .answer-inspector {
      background: var(--surface);
      border-color: var(--border);
    }.ds-type-menu {
	      background: var(--surface);
	      border-color: var(--border);
	      box-shadow: var(--shadow-float);
	    }.input-wrap,
    .library-filter,
    .upload-text-input,
    .ds-filter,
    .ds-detail-desc,
    .ds-technical-input,
    .ds-upload-input,
    .ds-upload-description,
    .zpravy-day-select,
    .question-input {
      background: var(--surface);
      border-color: var(--border-input);
      color: var(--ink);
    }

    #input-area form {
      border-top-color: transparent;
    }

    .question-input:empty::before {
      color: var(--faint);
    }

    .input-wrap,
    .question-input {
      background: var(--surface);
    }

    .input-wrap {
      border-color: var(--border);
      box-shadow: 0 18px 42px rgba(15, 23, 42, 0.08);
    }

    .input-wrap:focus-within {
      border-color: var(--border-input);
      box-shadow: 0 20px 46px rgba(15, 23, 42, 0.11);
    }

    .input-wrap.multiline .composer-footer::before {
      background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--surface) 84%);
    }

    .upload-section,
    .data-source-card,
    .chunk-card,
    .data-export-card,
    .upload-modal-file-item,
    .ds-item,
    .ds-detail,
    .ds-sheet,
    .ds-upload-modal,
    .zpravy-article {
      background: var(--surface);
      border-color: var(--border);
      color: var(--ink);
      box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
    }

    /* The neutralising these two rules used to do is in base.css now: the header
       is defined once rather than built dark and then undone. */

    /* The page ground runs behind the toolbar too; a white band across the
       top made the header look like a separate sheet laid on the page. */
    .library-toolbar-shell::before { display: none; }

    /* Every area lets the flax page ground through, the way #chat-area does.
       Warm white is reserved for what sits on top of it -- cards, panels,
       the composer -- so those read as raised rather than as the norm. */
    .library-area,
    .zpravy-area {
      background: transparent;
    }

    /* Quiet, like the day arrows in Zprávy: a header control earns attention by
       being where it is expected, not by being tinted. */
    .library-upload-btn {
      border: 0;
      background: transparent;
      color: var(--muted);
      box-shadow: none;
    }

    .library-upload-btn[hidden] {
      display: none !important;
    }

    .library-upload-btn:hover {
      background: var(--hover-bg);
      color: var(--ink);
    }
    .library-title {
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 27px;
      font-weight: 500;
      line-height: 1.1;
      letter-spacing: -.022em;
    }

    /* The heading opens the category menu, so it has to stay a heading: the
       button keeps none of its own chrome and inherits the title face, and
       only the chevron and a hover tint say that it does anything. The
       negative start margin pulls that tint's padding back so the text still
       lines up with the cards underneath. */
    .library-title-dd {
      min-width: 0;
    }

    .library-title-btn {
      display: inline-flex;
      align-items: center;
      gap: 9px;
      /* A percentage cap here is circular: the shrink-to-fit heading is sized
         from this button, then the button is capped to that already-smaller
         heading. That clipped even "Knihovna" while most of the row was empty. */
      max-width: min(36rem, 45vw);
      margin-inline-start: -9px;
      padding: 3px 9px;
      border: 0;
      border-radius: 11px;
      background: transparent;
      color: inherit;
      font: inherit;
      letter-spacing: inherit;
      cursor: pointer;
      transition: background .15s;
    }

    .library-title-btn > span {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .library-title-btn:hover,
    .library-title-btn:focus-visible {
      background: var(--hover-bg);
    }

    .library-title-btn .ds-type-dd-chev {
      width: 17px;
      height: 17px;
      flex: 0 0 auto;
      opacity: .5;
      transition: transform .18s, opacity .15s;
    }

    .library-title-btn:hover .ds-type-dd-chev,
    .library-title-btn:focus-visible .ds-type-dd-chev {
      opacity: .8;
    }

    .library-title-btn[aria-expanded="true"] .ds-type-dd-chev {
      transform: rotate(180deg);
      opacity: .8;
    }

    @media (prefers-reduced-motion: reduce) {
      .library-title-btn,
      .library-title-btn .ds-type-dd-chev {
        transition: none;
      }
    }

    .library-name {
      color: var(--ink);
    }

    .library-meta {
      margin-top: 3px;
      font-size: 12px;
      color: var(--faint);
      font-variant-numeric: tabular-nums;
    }

    .library-list {
      display: block;
    }

    /* The library shows publications and then everything else. A heading over the
       second group named what the cards under it plainly are, and it was the
       first thing on the page; a rule draws the same boundary without spending a
       line on it. */
    .library-section + .library-section {
      margin-top: 28px;
      padding-top: 28px;
      border-top: 1px solid var(--border-soft);
    }

    .library-publication-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
      gap: 18px;
      align-items: stretch;
    }

    .library-document-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
      gap: 14px;
      align-items: stretch;
    }

    .library-item.library-publication-item {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      min-height: 0;
      padding: 0;
      overflow: hidden;
    }

    .library-publication-cover {
      position: relative;
      display: grid;
      place-items: center;
      width: 100%;
      aspect-ratio: 210 / 297;
      overflow: hidden;
      background: var(--surface-inset);
    }

    .library-publication-cover img {
      position: absolute;
      inset: 0;
      display: block;
      width: 100%;
      height: 100%;
      object-fit: contain;
      object-position: center;
    }

    /* Stands in for the cover when it cannot be rendered. It now carries the
       whole document name rather than the series, so it needs room to wrap. */
    .library-publication-cover-fallback {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 7;
      overflow: hidden;
      padding: 0 16px;
      color: var(--muted);
      font-family: var(--font-display);
      font-size: 17px;
      line-height: 1.22;
      text-align: center;
    }

    /* `object-fit: contain` letterboxes anything that is not A4, and the bars
       are transparent -- without this the placeholder would read through them.
       The image is removed on error, which reveals the placeholder again. */
    .library-publication-cover img + .library-publication-cover-fallback {
      display: none;
    }

    .library-publication-item .library-summary-btn {
      background: rgb(var(--surface-page-rgb) / .88);
    }

    /* No border: it was a leftover blue from the slate palette and it drew a
       hard edge round every thing you said. White on the flax ground separates
       the bubble on its own, and matches the composer the text came from. */
    .message.user .bubble {
      background: var(--surface);
      border-color: transparent;
      color: var(--ink);
    }

    .agent-step,
    .agent-step.nested,
    .agent-step .step-body pre {
      background: transparent;
      border-color: transparent;
      color: var(--text);
    }

    .agent-step .step-body .step-arg-label {
      color: var(--ink);
    }

    .agent-step .step-body .step-code-kind {
      color: var(--blue);
    }
    .zpravy-side-controls {
      border-color: var(--border-input);
    }

    @media (max-width: 1100px) {
      :root {
        --rail-width: clamp(224px, 22vw, 248px);
        --main-pad: 20px;
      }
      .library-wrap {
        max-width: 100%;
      }
      .library-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
      .zpravy-area {
        padding: var(--main-pad) var(--main-pad) var(--main-pad) calc(var(--rail-width) + var(--main-pad));
      }
      .zpravy-layout {
        grid-template-columns: 1fr;
      }
      .zpravy-side {
        position: static;
        max-height: none;
        order: -1;
      }
    }

    @media (max-width: 720px) {
      :root {
        --rail-width: 260px;
        --main-pad: 18px;
      }
      .mobile-rail-toggle {
        display: grid;
      }
      .rail-backdrop {
        display: block;
        z-index: 61;
        opacity: 0;
        pointer-events: none;
        transition: opacity .18s ease;
      }
      body.rail-open .rail-backdrop {
        opacity: 1;
        pointer-events: auto;
      }
      body.answer-inspector-modal-open .rail-backdrop {
        z-index: 119;
        opacity: 1;
        pointer-events: auto;
      }
      .left-rail {
        z-index: 62;
        transform: translateX(calc(-100% - 14px));
        transition: transform .2s ease;
        box-shadow: 18px 0 44px rgba(15, 23, 42, 0.14);
      }
      body.rail-open .left-rail {
        transform: translateX(0);
      }
      body.rail-open .mobile-rail-toggle {
        visibility: hidden;
        pointer-events: none;
      }
      body.answer-inspector-modal-open .mobile-rail-toggle {
        visibility: hidden;
        pointer-events: none;
      }
      .answer-inspector {
        width: min(420px, calc(100vw - 64px));
      }
      .answer-inspector .answer-inspector-back {
        display: none;
      }
      body.answer-inspector-open #chat-area {
        padding-right: var(--main-pad);
      }
      body.answer-inspector-open #input-area {
        right: 0;
      }
      #chat-area,
    .library-area,
    .zpravy-area,
    .datasources-area {
        padding-left: var(--main-pad);
      }
      #input-area {
        left: 0;
        right: 0;
        padding-inline: 10px;
      }
      .library-area {
        padding: 18px;
      }
	      .library-toolbar-shell {
	        margin-bottom: 20px;
	      }
      .library-toolbar {
        flex-direction: column;
        align-items: stretch;
        flex-wrap: wrap;
        gap: 10px;
      }
      .library-toolbar-actions {
        width: 100%;
        flex-basis: 100%;
        flex-wrap: wrap;
      }
      .library-filter {
        width: 100%;
        flex: 1 1 100%;
      }
      .library-upload-btn {
        width: 40px;
      }
      .library-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
      .ds-detail-heading {
        grid-template-columns: 1fr;
        gap: 12px;
      }
      .ds-detail-title-row {
        width: 100%;
      }
      .ds-detail-tabs {
        justify-self: start;
        justify-content: flex-start;
        max-width: 100%;
        width: 100%;
      }
      .ds-detail-tab {
        padding-inline: 9px;
      }
    }

    @media (max-width: 520px) {
      .library-list {
        grid-template-columns: 1fr;
      }
    }

    .zpravy-article:hover {
      background: var(--card-hover-bg);
      border-color: var(--border-card-hover);
    }

    .library-item:focus-visible {
      outline: 2px solid #172033;
      outline-offset: 3px;
    }

    .app-floating-tooltip {
      position: fixed;
      z-index: 2147483647;
      max-width: calc(100vw - 1.5rem);
      /* Light, like every other floating surface in the app. The dark chip it
         replaced was the last piece of the slate era, and a paragraph of Czech
         prose reversed out of near-black is the hardest way to read a summary. */
      border: 1px solid var(--border);
      border-radius: var(--r-lg);
      background: var(--surface);
      color: var(--text);
      /* No drop shadow on a label chip. --shadow-pop is a 42px blur meant to
         lift a modal off the page; under a small tooltip on a light ground it
         reads as a soft round halo rather than as depth. The border does the
         separating, which is all a label this size needs. The wide document
         summary is the exception and takes --shadow-float below. */
      box-shadow: none;
      pointer-events: none;
      opacity: 0;
      visibility: hidden;
      transform: translateY(2px);
      transition: opacity 0.08s ease, transform 0.08s ease, visibility 0.08s;
    }

    .app-floating-tooltip.visible {
      opacity: 1;
      visibility: visible;
      transform: translateY(0);
    }

    .app-floating-tooltip.compact {
      width: max-content;
      padding: 0.4rem 0.6rem;
      font-size: 0.75rem;
      font-weight: 500;
      line-height: 1.2;
      color: var(--ink);
      white-space: nowrap;
    }

    /* The summary is the one tooltip wide enough to be mistaken for a card: same
       white, same hairline, sitting in the same grid. So this one takes the app's
       float shadow and an opaque ground -- the depth is what says "above", and a
       translucent ground let the card underneath bleed through and flatten it.
       The radius stays at --r-lg, a step tighter than the 14px cards. */
    .library-document-tooltip:not(.compact) {
      width: clamp(16rem, 25vw, 20rem);
      padding: 0.75rem 0.85rem;
      background: var(--surface);
      border-radius: 10px;
      box-shadow: 0 3px 10px rgba(27, 30, 22, .08);
      font-size: 14px;
      line-height: 1.5;
    }

    .library-document-tooltip-summary {
      text-wrap: pretty;
    }

	    .ds-item {
	      background: transparent;
	      border-bottom: 1px solid var(--border-soft);
	      box-shadow: none;
	    }

	    .ds-item:hover {
	      background: var(--surface-inset);
	    }

	    .ds-item.keyboard-active {
	      background: var(--surface-inset);
	    }

	    .ds-item.active {
	      box-shadow: none;
	    }

    .ds-detail:has(> .ds-detail-empty) {
      background: var(--surface);
      border-color: var(--border);
      box-shadow: none;
    }

	    .ds-type-dd-btn {
	      background: transparent;
	    }	    .chunk-card .meta span {
	      border-color: var(--blue);
    }
    .data-source-card:hover {
      background: var(--surface-page);
      border-color: var(--border-card-hover);
      box-shadow: 0 2px 7px rgba(15, 23, 42, .06);
    }

    .data-source-name {
      color: var(--text);
    }

    .data-source-card:hover .data-source-name {
      color: var(--ink);
    }

    .data-source-card:focus-visible {
      outline: 2px solid var(--faint);
      outline-offset: 2px;
    }

    .data-source-description {
      color: var(--muted);
    }

    .library-empty {
      background:
        radial-gradient(circle at 50% 0%, rgba(34, 197, 94, 0.12), transparent 48%),
        linear-gradient(180deg, #ffffff, #f8fbff);
      border-color: var(--border);
      color: var(--muted);
      box-shadow: 0 16px 42px rgba(15, 23, 42, 0.08);
    }

    .library-empty.compact-loader {
      background: transparent;
      border-color: transparent;
      box-shadow: none;
    }

    .upload-label,
    .upload-dropzone-label,
    .chunk-card .meta,
    .chunk-card .chunk-content,
    .agent-step-head .step-meta,
    .agent-step .step-body,
    .loading,
    .empty-state,
    .source-picker-empty,
    .upload-modal-dropzone-text,
    .upload-modal-dropzone-hint,
    .upload-modal-file-name,
    .upload-modal-status,
    .ds-detail-empty,
    .ds-detail-sub,
    .ds-save-status,
    .ds-upload-hint,
    .ds-upload-status,
    .ds-upload-label,
    .ds-upload-sheets,
    .inline-status-dots,
    .zpravy-loading,
    .zpravy-article-summary,
    .zpravy-article-meta,
    .zpravy-empty {
      color: var(--muted) !important;
    }

    .ds-detail-section-title {
      color: var(--ink);
    }

    .empty-state {
      background: transparent;
      border: 0;
      box-shadow: none;
    }

    .empty-state h2 {
      color: var(--ink);
    }

    .empty-state p {
      color: var(--muted);
    }.answer-text,
    .library-name,
    .ds-item-name,
    .ds-sheet-table,
    .agent-step-head,
    .agent-step-head .step-label,
    .source-picker-item {
      color: var(--ink);
    }

    .answer-text {
      font-size: 16px;
      line-height: 1.65;
      letter-spacing: -0.004em;
    }

    .answer-text a {
      color: var(--blue);
      text-decoration-color: rgba(29, 79, 145, 0.42);
      text-decoration-thickness: 1px;
      text-underline-offset: 2px;
      transition: color 0.14s ease, text-decoration-color 0.14s ease;
    }

    .answer-text a:visited {
      color: var(--blue);
    }

    .answer-text a:hover {
      color: var(--blue);
      text-decoration-color: currentColor;
    }

    .answer-text strong {
      color: var(--ink);
      font-weight: 650;
    }

    .answer-text code {
      border: 0;
      padding: 0;
      background: transparent;
      color: var(--text);
      font-family: inherit;
      font-size: 0.94em;
      font-weight: 560;
    }

    .answer-text pre {
      margin: 0.85em 0;
      padding: 12px 14px;
      overflow-x: auto;
      border: 1px solid var(--border-input);
      border-radius: 7px;
      background: var(--surface-page);
      color: var(--ink);
      line-height: 1.5;
    }

    .answer-text pre code {
      padding: 0;
      border: 0;
      border-radius: 0;
      background: transparent;
      color: inherit;
      font-size: 0.88em;
    }

    .answer-text table.md-table {
      background: transparent;
      border-color: transparent;
      color: var(--ink);
      box-shadow: none;
    }

    .ds-sheet-table {
      background: transparent;
      border: 0;
      color: var(--ink);
      box-shadow: none;
      font-size: 12.5px;
      font-variant-numeric: tabular-nums;
      letter-spacing: -0.005em;
    }

    .table-copy-wrapper {
      border-color: transparent;
      background: transparent;
      box-shadow: none;
    }

    .answer-text table.md-table th,
    .answer-text table.md-table td {
      border-color: var(--border-soft);
    }

    .answer-text table.md-table thead th {
      background: transparent;
      border-color: var(--border-card-hover);
      color: var(--ink-strong);
    }

    .ds-sheet-table th {
      position: sticky;
      top: 0;
      z-index: 3;
      background: linear-gradient(180deg, var(--surface-page), var(--hover-bg));
      border-bottom: 1px solid var(--border-input);
      color: var(--ink);
      font-size: 12px;
      font-weight: 600;
      letter-spacing: 0.005em;
      padding: 10px 12px;
      box-shadow: 0 1px 0 rgba(15, 23, 42, 0.04);
    }

    .answer-text table.md-table tbody tr:nth-child(even) {
      background: transparent;
    }

    .ds-sheet-table td {
      border-bottom: 1px solid var(--border-soft);
      color: var(--ink);
      padding: 8px 12px;
      background: rgba(255, 255, 255, 0.72);
      max-width: 360px;
    }

    .ds-sheet-table tbody tr:nth-child(even) td {
      background: rgba(247, 250, 252, 0.88);
    }

    .ds-sheet-table tbody tr:hover td {
      background: var(--card-hover-bg);
    }

    .source-picker-btn,
    .library-open,
    .answer-action-btn,
    .ds-btn,
    .ds-upload-cancel {
      background: var(--surface);
      border-color: var(--border-input);
      color: var(--text);
    }

    .composer-footer .source-picker-btn {
      background: transparent;
      border-color: transparent;
      color: var(--ink-strong);
      box-shadow: none;
    }

    .source-picker-btn:hover,
    .answer-action-btn:hover,
    .ds-btn:hover,
    .ds-upload-cancel:hover {
      background: var(--card-hover-bg);
      border-color: var(--green);
      color: var(--ink);
    }

    .composer-footer .source-picker-btn:hover {
      background: var(--hover-bg);
      border-color: transparent;
      color: var(--accent-hover);
    }

    #send-btn,
    .table-copy-btn,
    .upload-btn,
    .ds-upload-btn,
    .ds-btn.primary,
    .ds-upload-submit,
    .ds-upload-save {
      background: var(--green);
      border-color: var(--green);
      color: var(--on-accent);
    }

    .composer-footer #send-btn {
      background: var(--accent);
      border-color: var(--accent);
      color: var(--on-accent);
      border-radius: 999px;
      box-shadow: none;
    }

	    #send-btn:hover,
    .table-copy-btn:hover,
    .upload-btn:hover,
    .ds-upload-btn:hover,
    .ds-btn.primary:hover,
    .ds-upload-submit:hover,
    .ds-upload-save:hover {
	      background: var(--green-hover);
	      border-color: var(--green-hover);
	    }

    .composer-footer #send-btn:hover {
      background: var(--accent-hover);
      border-color: var(--accent-hover);
    }

    .composer-footer #send-btn.is-voice-stop,
    .composer-footer #send-btn.is-voice-stop:hover {
      background: var(--red);
      border-color: var(--red);
    }

	    .ds-upload-btn {
	      border-color: var(--green-border);
	      box-shadow: none;
	    }
    #send-btn:disabled,
    .upload-btn:disabled {
      background: var(--border-soft);
      color: var(--faint);
    }
    .composer-footer #send-btn.is-uploading,
    .composer-footer #send-btn.is-uploading:hover {
      background: var(--muted);
      border-color: var(--muted);
      color: var(--surface);
      opacity: 1;
    }

    .upload-dropzone,
    .upload-modal-dropzone,
    .ds-upload-dropzone {
      background: var(--surface-inset);
      border-color: var(--border-card-hover);
      color: var(--muted);
    }

    .upload-dropzone:hover,
    .upload-dropzone.drag-over,
    .upload-modal-dropzone:hover,
    .upload-modal-dropzone.drag-over,
    .ds-upload-dropzone:hover,
    .ds-upload-dropzone.drag {
      background: var(--green-soft);
      border-color: var(--green);
    }

    .upload-modal-overlay,
    .ds-upload-overlay {
      background: rgba(15, 23, 42, .36);
    }

    .upload-modal-header,
    .upload-modal-footer,
    .source-picker-header,
    .upload-modal-file-item,
    .ds-upload-header,
    .ds-upload-actions,
    .source-picker-item {
      border-color: var(--border);
    }

    .source-picker-item.active {
      background: var(--active-bg);
    }

    .upload-modal-file-item {
      background: var(--surface);
      border-color: var(--border);
    }

    .upload-modal-file-name {
      color: var(--ink);
    }

    .upload-modal-file-docname {
      background: var(--surface-inset);
      border-color: var(--border-card-hover);
      color: var(--ink);
    }

    .upload-modal-file-docname::placeholder {
      color: var(--faint);
    }

    .chunk-card .meta a,
    .answer-text a.citation-link,
    .agent-step-head .step-action {
      color: var(--blue);
    }

    .message.user .label {
      color: var(--blue);
    }

    .message.assistant .label,
    .zpravy-article-source,
    .upload-modal-status.success,
    .ds-upload-filename {
      color: var(--green);
    }
    .not-reliable,
    .upload-modal-status.error,
    .agent-step .step-error {
      color: var(--red);
    }

    .chunk-card .meta {
      color: var(--muted);
      gap: 10px;
    }

    .chunk-card .meta span {
      background: var(--hover-bg);
      border: 1px solid var(--border-input);
      color: var(--muted);
      border-radius: 999px;
      padding: 3px 9px;
      font-weight: 500;
    }

    .document-source-title {
      flex: 1 1 auto;
      min-width: 0;
      text-decoration: none;
    }

    a.document-source-title:hover {
      text-decoration: underline;
      text-underline-offset: 3px;
    }

    /* Keep the document mark attached to the name, not centred between the
       name and its page links. The links form a second row aligned with the
       title, so the row reads as document first and locations second. */
    .document-source-card {
      display: grid;
      grid-template-columns: 20px minmax(0, 1fr);
      column-gap: 10px;
      row-gap: 3px;
    }

    .document-source-heading {
      display: grid;
      grid-column: 1 / -1;
      grid-template-columns: 20px minmax(0, 1fr);
      align-items: center;
      column-gap: 10px;
      min-width: 0;
    }

    .document-source-heading .data-source-icon {
      width: 20px;
      height: 20px;
      margin-top: 0;
    }

    /* The pages sit right under the document's name and read at nearly its
       size. They were set small and prefixed with the word "Strany", which made
       them look like a metadata line about the row rather than what they are:
       the places in the file you can go. The word said nothing that a number
       under a document title does not already say. */
    /* Ordinary inline text rather than a flex row: the numbers are separated by
       commas, and a comma has to sit tight against the number before it. A gap
       either side -- which is all a flex row can offer -- makes it read as a
       bullet that happens to be comma-shaped. Inline flow also wraps the list
       the way a sentence wraps, which is what it is. */
    .document-source-pages {
      grid-column: 2;
      min-width: 0;
      margin: 0;
      line-height: 1.5;
    }

    .document-source-sep {
      color: var(--muted);
      font-size: 13px;
      user-select: none;
    }

    .document-source-page {
      color: var(--muted);
      font-size: 13px;
      font-weight: 500;
      font-variant-numeric: tabular-nums;
      white-space: nowrap;
      text-decoration: none;
      transition: color var(--dur) var(--ease-out);
    }

    a.document-source-page:hover {
      color: var(--ink);
      text-decoration: underline;
      text-underline-offset: 3px;
    }

    .answer-inspector-content[data-view="resources"]:not(:has(.analysis-solution)) {
      overflow-y: auto;
    }

    /* One selected PDF becomes a small form, not a one-item upload queue. */
    #upload-modal-overlay .upload-modal {
      width: min(540px, calc(100vw - 32px));
      font-family: var(--font-sans);
      color: var(--text);
    }
    #upload-modal-overlay .upload-modal-header { padding: 18px 20px 14px; border-bottom: 0; }
    #upload-modal-overlay .upload-modal-title { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
    #upload-modal-overlay .upload-modal-close {
      width: 30px;
      height: 30px;
      display: grid;
      place-items: center;
      padding: 0;
      border-radius: var(--r-md);
    }
    #upload-modal-overlay .upload-modal-close svg {
      width: 17px;
      height: 17px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
    }
    #upload-modal-overlay .upload-modal-body { padding: 4px 20px 8px; }
    .upload-modal-dropzone { padding: 26px 20px; margin-bottom: 14px; }
    .upload-modal-dropzone[hidden] { display: none; }
    .upload-modal-dropzone-icon {
      width: 34px;
      height: 34px;
      display: grid;
      place-items: center;
      margin: 0 auto 10px;
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--ink);
      font-size: 0;
    }
    .upload-modal-dropzone-icon svg {
      width: 19px;
      height: 19px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.6;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .upload-modal-dropzone-text { color: var(--ink) !important; font-size: 13.5px; font-weight: 500; }
    .upload-modal-dropzone-hint { margin-top: 3px; font-size: 12px; }
    .upload-modal-filelist { display: block; }
    .upload-modal-file-item {
      display: block;
      padding: 2px 0 6px;
      border: 0;
      border-radius: 0;
      box-shadow: none;
    }
    .upload-modal-selected-file {
      display: grid;
      grid-template-columns: 32px minmax(0, 1fr) auto;
      align-items: center;
      gap: 10px;
      padding: 10px 12px;
      border-radius: var(--r-md);
      background: var(--surface-inset);
    }
    .upload-modal-file-icon {
      width: 28px;
      height: 28px;
      display: grid;
      place-items: center;
      border: 1px solid var(--border);
      border-radius: var(--r-sm);
      color: var(--muted);
    }
    .upload-modal-file-icon svg {
      width: 17px;
      height: 17px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.55;
      stroke-linecap: round;
    }
    .upload-modal-file-name {
      min-width: 0;
      overflow: hidden;
      color: var(--text) !important;
      font-size: 12.5px;
      font-weight: 500;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .upload-modal-file-change {
      padding: 5px 7px;
      border: 0;
      border-radius: var(--r-sm);
      background: transparent;
      color: var(--muted);
      font: 12px var(--font-sans);
      cursor: help;
    }
    .upload-modal-file-change:hover {
      background: var(--hover-bg);
      color: var(--ink);
    }
    .upload-modal-file-fields {
      display: grid;
      gap: 12px;
      margin-top: 16px;
    }
    .upload-modal-field {
      display: grid;
      gap: 6px;
      color: var(--muted);
      font-size: 11.5px;
      font-weight: 500;
    }
    .upload-modal-field[hidden] { display: none; }
    .upload-modal-file-series,
    .upload-modal-file-edition,
    .upload-modal-file-date input,
    .upload-modal-file-docname {
      min-width: 0;
      width: 100%;
      height: 36px;
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--text);
      padding: 0 10px;
      font: 13px var(--font-sans);
    }
    .upload-modal-file-series:focus,
    .upload-modal-file-edition:focus,
    .upload-modal-file-date input:focus,
    .upload-modal-file-docname:focus {
      border-color: var(--border-focus);
      outline: 0;
    }
    #upload-modal-overlay .upload-modal-footer { justify-content: flex-end; padding: 12px 20px 18px; border-top: 0; }

    #document-edit-overlay .document-edit-modal {
      width: min(460px, calc(100vw - 32px));
      font-family: var(--font-sans);
    }
    #document-edit-overlay .upload-modal-header { padding: 18px 20px 10px; border-bottom: 0; }
    #document-edit-overlay .upload-modal-close svg {
      width: 17px;
      height: 17px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
    }
    .document-edit-form { padding: 6px 20px 18px; }
    .document-metadata-field {
      display: grid;
      gap: 6px;
      margin-top: 12px;
      color: var(--muted);
      font-size: 11.5px;
      font-weight: 500;
    }
    .document-metadata-field[hidden] { display: none; }
    .document-metadata-field input,
    .document-metadata-field select {
      width: 100%;
      height: 38px;
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--ink);
      padding: 0 11px;
      font: 13px var(--font-sans);
    }
    .document-metadata-field input:focus,
    .document-metadata-field select:focus {
      border-color: var(--green);
      outline: 0;
      box-shadow: 0 0 0 2px var(--green-soft);
    }
    .document-metadata-error { margin-top: 12px; color: var(--red); font-size: 12px; }
    .document-metadata-error[hidden] { display: none; }
    .document-edit-footer { padding: 16px 0 0; border-top: 0; }

    .library-card-actions {
      position: absolute;
      top: 9px;
      right: 9px;
      z-index: 2;
      display: flex;
      align-items: center;
      gap: 4px;
    }

    .library-summary-btn {
      width: 30px;
      height: 30px;
      display: grid;
      place-items: center;
      border: 0;
      border-radius: 50%;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
      transition: opacity var(--dur) var(--ease-out), background var(--dur) var(--ease-out);
    }
    .library-summary-btn { opacity: 0; }
    .library-summary-btn svg {
      width: 18px;
      height: 18px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.6;
      stroke-linecap: round;
    }
    .library-item:hover .library-summary-btn,
    .library-item:focus-within .library-summary-btn,
    .library-summary-btn:focus-visible { opacity: 1; }
    .library-summary-btn:hover,
    .library-summary-btn:focus-visible { background: var(--hover-bg); color: var(--ink); }

    /* An upload belongs where the document will live. It occupies the first
       grid slot as a quiet, non-interactive card and is replaced by the real
       card as soon as the refreshed catalogue contains it. */
    .library-item.library-upload-item,
    .library-item.library-upload-item:hover {
      position: relative;
      overflow: hidden;
      cursor: default;
      border-color: var(--border-soft);
      background: var(--surface-inset);
      box-shadow: none;
      transform: none;
    }

    .library-upload-item .library-name { color: var(--muted); }

    .library-upload-status {
      display: flex;
      align-items: center;
      gap: 6px;
      margin-top: 5px;
      color: var(--faint);
      font-size: 11.5px;
      line-height: 1.25;
    }

    .library-upload-spinner {
      flex: 0 0 9px;
      width: 9px;
      height: 9px;
      border: 1.5px solid var(--border-card-hover);
      border-top-color: var(--green-deep);
      border-radius: 50%;
      animation: spin 850ms linear infinite;
    }

    .library-upload-progress {
      position: absolute;
      right: 0;
      bottom: 0;
      left: 0;
      height: 2px;
      overflow: hidden;
      background: var(--border-soft);
    }

    .library-upload-progress span {
      display: block;
      height: 100%;
      border-radius: 0 var(--r-pill) var(--r-pill) 0;
      background: var(--green);
      transition: width .45s var(--ease-out);
    }

    .library-upload-status.error { color: var(--red); }
    .library-upload-error-mark { font-weight: 700; }
    .library-upload-done-mark { color: var(--green-deep); font-weight: 700; }

    .library-upload-dismiss {
      position: absolute;
      top: 9px;
      right: 9px;
      display: grid;
      width: 28px;
      height: 28px;
      place-items: center;
      border: 0;
      border-radius: 50%;
      background: transparent;
      color: var(--faint);
      cursor: pointer;
    }

    .library-upload-dismiss:hover { background: var(--hover-bg); color: var(--ink); }
    .library-upload-dismiss svg {
      width: 15px;
      height: 15px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
    }

    @media (max-width: 640px) {
      .upload-modal-file-item { grid-template-columns: 28px minmax(0, 1fr) 30px; gap: 9px; }
    }

    .chunk-card .meta a,
    .agent-step-head .step-action {
      color: var(--blue);
      font-weight: 600;
    }

    .sources-toggle,
    .agent-trace-toggle,
    .analysis-solution-toggle {
      color: var(--muted);
      font-weight: 400;
    }

    .sources-toggle:hover,
    .agent-trace-toggle:hover,
    .analysis-solution-toggle:hover {
      color: var(--text);
    }

    .analysis-solution {
      color: var(--text);
    }

    .analysis-solution-card {
      background: transparent;
    }
    .analysis-solution-code {
      background: rgba(248, 250, 252, 0.72);
      color: var(--ink-strong);
    }

    .chat-history-status {
      color: var(--muted);
    }
    .upload-modal-status.running,
    .ds-upload-status.running {
      color: var(--red);
    }

    #send-btn.is-stop {
      background: var(--accent);
      border-color: var(--accent);
      color: var(--on-accent);
    }
    #send-btn.is-stop:hover {
      background: var(--accent-hover);
      border-color: var(--accent-hover);
    }

    /* The strip under the composer is the page ground, not a white shelf: the
       gradient exists so messages fade out as they scroll beneath it, which
       only works if it fades to the colour actually behind them. */
    #input-area {
      background: linear-gradient(
        to top,
        var(--surface-page) 0%,
        rgb(var(--surface-page-rgb) / .96) 74%,
        rgb(var(--surface-page-rgb) / 0) 100%
      );
    }

    body.chat-empty #input-area {
      background: transparent;
    }

    .agent-step {
      background: rgba(248, 250, 252, 0.82);
      border-color: var(--border-soft);
    }

    .agent-step.nested {
      background: rgba(241, 245, 249, 0.74);
    }

    .agent-step-head .step-action {
      color: var(--text);
      font-weight: 650;
    }

    .agent-trace-summary {
      flex: 0 0 auto;
      margin: 0 0 12px;
      padding: 2px 4px 14px;
      border-bottom: 1px solid var(--border-soft);
    }

    .agent-trace-summary-group + .agent-trace-summary-group {
      margin-top: 14px;
      padding-top: 13px;
      border-top: 1px solid var(--border-soft);
    }

    .agent-trace-summary-label {
      margin-bottom: 8px;
      color: var(--muted);
      font-size: 10px;
      font-weight: 650;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }

    .agent-trace-summary-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(64px, 1fr));
      gap: 12px;
    }

    .agent-trace-metric {
      display: flex;
      flex-direction: column;
      gap: 2px;
      min-width: 0;
    }

    .agent-trace-metric strong {
      color: var(--ink);
      font-size: 15px;
      font-weight: 650;
      font-variant-numeric: tabular-nums;
    }

    .agent-trace-metric span {
      color: var(--muted);
      font-size: 11px;
      font-weight: 400;
    }

    @media (max-width: 560px) {
      .agent-trace-summary-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: 8px;
      }
    }

    .agent-step-head .step-num,
    .agent-step-head .step-label,
    .agent-step .step-body .step-code-kind {
      color: var(--muted);
    }

    .agent-step .step-body pre {
      background: transparent;
      border-color: transparent;
    }

    .agent-step > summary.agent-step-head {
      list-style: none;
      cursor: pointer;
      user-select: none;
    }

    .agent-step > summary.agent-step-head::-webkit-details-marker {
      display: none;
    }

    .agent-step .step-toggle-icon {
      width: 7px;
      height: 7px;
      margin-left: auto;
      border-right: 1.5px solid var(--muted);
      border-bottom: 1.5px solid var(--muted);
      transform: rotate(45deg);
      transition: transform 0.15s ease;
      flex: 0 0 auto;
    }
    .agent-step[open] .step-toggle-icon {
      transform: rotate(225deg);
    }

    .agent-trace.open,
    .sources-list.open,
    .analysis-solution.open {
      margin-top: 10px;
      padding: 12px;
      background: var(--surface-inset);
      border: 1px solid var(--border-soft);
      border-radius: var(--r-lg);
      box-shadow: none;
      overflow: hidden;
    }

    .agent-trace,
    .agent-step,
    .agent-step .step-body {
      min-width: 0;
      max-width: 100%;
    }

    .agent-step .step-body {
      max-height: min(560px, 60vh);
      overflow-y: auto;
      overflow-x: hidden;
      overscroll-behavior: contain;
      scrollbar-gutter: stable;
    }

    .agent-step .step-body pre,
    .agent-step .step-body pre.step-code {
      max-width: 100%;
      box-sizing: border-box;
      white-space: pre-wrap;
      overflow-wrap: anywhere;
      word-break: break-word;
      overflow-x: hidden;
    }

    .agent-trace.open > .agent-step:first-child,
    .sources-list.open > .chunk-card:first-child,
    .sources-list.open > .data-source-list:first-child,
    .analysis-solution.open > .analysis-solution-card:first-child {
      margin-top: 0;
    }

    /* Canonical catalogue editor */
    .datasources-area {
      padding: 0 0 0 var(--rail-width);
      background: var(--surface-page);
    }

    .datasources-wrap {
      height: 100%;
      padding: 18px 20px 20px;
      box-sizing: border-box;
    }

    .datasources-body {
      height: 100%;
      grid-template-columns: clamp(15.5rem, 18vw, 19rem) minmax(0, 1fr);
      gap: 0;
      overflow: hidden;
      border: 1px solid var(--border);
      border-radius: var(--r-xl);
      background: var(--surface);
      box-shadow: var(--shadow-card);
    }

    .datasources-sidebar {
      border: 0;
      border-radius: var(--r-xl) 0 0 var(--r-xl);
      background: var(--surface-inset);
    }

    .datasources-sidebar-controls {
      gap: .65rem;
      min-height: 110px;
      box-sizing: border-box;
      padding: 1.05rem .95rem .9rem;
      border: 0;
      border-bottom: 1px solid var(--border-soft);
      background: var(--surface-inset);
    }

    .datasources-sidebar-title {
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 20px;
      font-weight: 500;
      line-height: 1.2;
      letter-spacing: -.015em;
    }

    .ds-search-row {
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .ds-search-row .ds-filter { flex: 1 1 auto; }

    .ds-type-dd-btn {
      padding: 6px 7px;
      border-radius: var(--r-sm);
      color: var(--text);
    }

    .ds-type-dd-btn:hover, .ds-type-dd-btn[aria-expanded="true"] { background: var(--hover-bg); color: var(--ink); }
    .ds-type-dd-btn.filtered { background: var(--active-bg); color: var(--ink); }

    .ds-type-menu-item {
      font-size: 13px;
      color: var(--text);
    }
    .ds-type-menu-item:hover { background: var(--hover-bg); color: var(--ink); }
    .ds-type-menu-item.active { background: var(--active-bg); color: var(--ink); font-weight: 600; }

    .ds-upload-btn {
      width: 32px;
      height: 32px;
      min-height: 32px;
      border: 0;
      border-radius: var(--r-sm);
      background: transparent;
      color: var(--text);
    }

    .ds-upload-btn:hover {
      border-color: transparent;
      background: var(--hover-bg);
      color: var(--ink);
      transform: none;
    }

    .ds-filter {
      min-height: 38px;
      padding: 8px 12px;
      border: 1px solid var(--border-input);
      border-radius: var(--r-md);
      background: rgba(254, 253, 251, .82);
      color: var(--ink);
      font-size: 13px;
    }

    .ds-filter:focus { border-color: var(--border-focus); }

    .ds-list {
      gap: 2px;
      padding: 7px 10px 16px;
      scrollbar-gutter: stable;
    }

    .ds-item {
      flex: 0 0 auto;
      min-height: 0;
      padding: 10px 12px;
      border: 0;
      border-radius: var(--r-sm);
    }

    .ds-item:hover,
    .ds-item.keyboard-active {
      background: var(--hover-bg);
    }
    .ds-item.active {
      background: var(--active-bg);
      box-shadow: none;
    }

    .ds-item-name {
      color: var(--ink);
      font-size: 13.25px;
      font-weight: 450;
      line-height: 1.42;
    }

    .ds-detail {
      border: 0;
      border-left: 1px solid var(--border-soft);
      border-radius: 0;
      background: var(--surface);
      box-shadow: none;
    }

    .ds-detail-header {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      min-height: 110px;
      box-sizing: border-box;
      padding: 0;
      border-bottom: 1px solid var(--border-soft);
      background: var(--surface);
    }

    .ds-detail-heading {
      display: flex;
      align-items: center;
      gap: 1rem;
      min-height: auto;
      padding: 1.25rem 1.55rem .75rem;
      box-sizing: border-box;
    }

    .ds-detail-title-row {
      width: min(100%, var(--zpravy-measure));
      max-width: var(--zpravy-measure);
      gap: .7rem;
    }

    .ds-detail-name {
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 21px;
      font-weight: 550;
      line-height: 1.25;
      letter-spacing: -.015em;
    }

    .ds-detail-controls {
      position: static;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      width: 100%;
      min-width: 0;
      padding: .15rem 1.55rem .95rem;
      transform: none;
    }

    .ds-detail-tabs { gap: 18px; }

    .ds-detail-tab {
      padding: 7px 2px 6px;
      border-radius: 0;
      border-bottom: 2px solid transparent;
      color: var(--muted);
      font-size: 12.5px;
      font-weight: 550;
    }

    /* Tabs are marked by a rule under the active label, not a filled shape.
       The pill this replaced was the loudest thing in a quiet UI, and it had to
       carry a tan strong enough to beat the surface, which made it louder still.
       The transparent border on the resting state reserves the 2px so switching
       tabs never shifts the row. Same pattern as .zz-tab on the Zelená page,
       which already worked this way. */
    .ds-detail-tab:hover {
      color: var(--ink);
      background: transparent;
    }

    .ds-detail-tab.active {
      color: var(--ink);
      background: transparent;
      border-bottom-color: var(--accent);
    }

    .ds-detail-tab:focus { outline: none; }

    .ds-detail-tab:focus-visible {
      border-radius: 2px;
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

    .ds-detail-actions {
      display: flex;
      align-items: center;
      gap: .5rem;
      margin-left: auto;
    }

    .ds-detail-download {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: .4rem;
      min-height: 34px;
      padding: 7px 12px;
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--ink);
      font-size: 13px;
      font-weight: 550;
      text-decoration: none;
      transition: background var(--dur) ease, border-color var(--dur) ease, transform var(--dur) ease;
    }

    .ds-detail-download svg {
      width: 16px;
      height: 16px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.8;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .ds-detail-download:hover {
      border-color: var(--border-card-hover);
      background: var(--hover-bg);
      transform: none;
    }

    .ds-detail-save {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      min-width: 88px;
      min-height: 34px;
      padding: 8px 16px;
      border: 0;
      border-radius: var(--r-pill);
      background: var(--accent);
      color: var(--on-accent);
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      margin-left: 0;
      transition: background var(--dur) ease, opacity var(--dur) ease, transform var(--dur) ease;
    }

    .ds-detail-save:hover:not(:disabled) { background: var(--accent-hover); transform: translateY(-1px); }
    .ds-detail-save:disabled {
      visibility: visible;
      cursor: default;
      opacity: .28;
      pointer-events: none;
    }
    .ds-detail-save[data-state="saved"] { background: var(--green-deep); }
    .ds-detail-save[data-state="error"] { background: var(--red); }

    .ds-detail-save-loader {
      display: none;
      width: 14px;
      height: 14px;
      border: 2px solid rgba(255, 255, 255, .35);
      border-top-color: var(--surface);
      border-radius: 50%;
      animation: spin .75s linear infinite;
    }

    .ds-detail-save.saving .ds-detail-save-label { display: none; }
    .ds-detail-save.saving .ds-detail-save-loader { display: block; }

    .ds-detail-content {
      padding: 1.8rem clamp(1.55rem, 2.4vw, 2.2rem) 2.4rem;
      background: var(--surface);
    }

    /* The preview bleeds past the column's padding on every side. At the bottom
       it now takes all of it (2.4rem, the column's own padding-bottom) rather
       than most: the strip that was left over is exactly what the horizontal
       scrollbar needs, so the bar sits in the gap under the table instead of
       costing the table a row of height. */
    .ds-detail-panel[data-detail-panel="preview"].active {
      margin: -1.8rem calc(-1 * clamp(1.55rem, 2.4vw, 2.2rem)) -2.4rem;
    }

    .ds-detail-panel[data-detail-panel="preview"] .ds-sheet-table-wrap {
      border-radius: 0;
    }

    /* The detail column stays up rather than fading like the app's auto-hiding
       ones: it is the only cue that the description continues below. */
    .ds-detail-content {
      scrollbar-width: thin;
      scrollbar-color: var(--scrollbar-thumb-strong) transparent;
      transition: none;
    }

    .ds-detail-content::-webkit-scrollbar { width: 8px; height: 8px; }
    .ds-detail-content::-webkit-scrollbar-track { background: transparent; }

    .ds-detail-content::-webkit-scrollbar-thumb,
    .ds-detail-content.is-scrolling::-webkit-scrollbar-thumb {
      background: var(--scrollbar-thumb-strong);
      border-radius: 999px;
      transition: none;
    }

    .ds-detail-content::-webkit-scrollbar-thumb:hover {
      background: var(--scrollbar-thumb-hover);
    }

    .ds-detail-content::-webkit-scrollbar-corner { background: transparent; }

    /* The preview table is read by dragging it sideways, so that bar is the one
       control here and it has to stay put: one size, always visible, in the
       app's own colours. Neither engine will do that with a native bar. Chrome
       ignores ::-webkit-scrollbar sizing as soon as any standard scrollbar
       property is set -- the app sets scrollbar-color on `*` -- and Firefox
       follows the Windows setting that thins and hides overlay bars whatever
       the page asks for. So both native bars go, js/sheet-scrollbar.js draws the
       horizontal one, and the rows keep the wheel and need no bar at all. */
    .ds-sheet-table-wrap {
      scrollbar-width: none;
      transition: none;
    }

    .ds-sheet-table-wrap::-webkit-scrollbar { width: 0; height: 0; }

    /* Keep the hit area comfortably tall, but paint only the thumb. A visible
       full-width rail looked like a second container under the table. */
    .ds-sheet-scrollbar {
      position: relative;
      flex: 0 0 auto;
      height: 13px;
      margin: 0 12px 4px;
      background: transparent;
    }

    .ds-sheet-scrollbar[hidden] { display: none; }

    /* The pointer gets the full 13px hit area. The thumb darkens like a native
       scrollbar on hover and again while held, without changing size. */
    .ds-sheet-scrollbar-thumb {
      position: absolute;
      top: 0;
      left: 0;
      height: 7px;
      min-width: 56px;
      border-radius: 999px;
      background: var(--scrollbar-thumb-strong);
      border-top: 3px solid transparent;
      border-bottom: 3px solid transparent;
      background-clip: padding-box;
      box-sizing: content-box;
      cursor: grab;
      touch-action: none;
      transition: background-color var(--dur) ease;
    }

    .ds-sheet-scrollbar-thumb:hover {
      background-color: var(--scrollbar-thumb-hover);
    }

    .ds-sheet-scrollbar-thumb.is-held {
      background-color: var(--faint);
      cursor: grabbing;
    }

    .ds-detail-panel { margin-top: 0; }
    .ds-detail-desc-field .ds-detail-section-title,
    .ds-technical-field .ds-detail-section-title {
      margin: 0 2px 7px;
      color: var(--muted);
      font-size: 11.5px;
      font-weight: 550;
      letter-spacing: .01em;
      text-transform: none;
    }

    .ds-detail-desc,
    .ds-technical-input,
    .ds-column-description,
    .ds-column-unit,
    .ds-relation-source,
    .ds-relation-local,
    .ds-relation-target,
    .ds-relation-description {
      border: 1px solid var(--border-soft);
      border-radius: var(--r-md);
      outline: 0;
      background: var(--surface-inset);
      color: var(--ink);
      box-shadow: none;
      transition: background var(--dur), border-color var(--dur);
    }

    .ds-detail-desc {
      min-height: 88px;
      padding: 10px 12px;
      font-size: 13.5px;
      line-height: 1.62;
      resize: none;
      field-sizing: content;
      max-height: 46vh;
    }

    .ds-detail textarea.ds-edit-control { resize: none; }

    .ds-description-row-meaning .ds-detail-desc { min-height: 64px; }
    .ds-description-rules .ds-detail-desc { min-height: 88px; }

    /* Fields sharing a grid row grow to equal height */
    .ds-detail-desc-field .ds-detail-desc { flex: 1 1 auto; }

    .ds-detail-desc {
      border-color: transparent;
    }

    .ds-detail-desc:hover { background: #f1f5f9; }

    .ds-detail-desc:focus,
    .ds-technical-input:focus,
    .ds-column-description:focus,
    .ds-column-unit:focus,
    .ds-relation-source:focus,
    .ds-relation-local:focus,
    .ds-relation-target:focus,
    .ds-relation-description:focus {
      border-color: var(--border-focus);
      background: var(--surface);
      box-shadow: none;
    }

    /* The public catalogue is an inspection surface. Its existing field
       structure still gives long metadata sensible wrapping, but it should
       read as content rather than as a disabled editor. */
    .ds-detail.is-readonly .ds-edit-control {
      pointer-events: none;
      cursor: default;
      opacity: 1;
    }

    .ds-detail.is-readonly .ds-detail-desc,
    .ds-detail.is-readonly .ds-technical-input,
    .ds-detail.is-readonly .ds-column-description,
    .ds-detail.is-readonly .ds-column-unit,
    .ds-detail.is-readonly .ds-relation-description {
      border-color: transparent;
      background: transparent;
    }

    .ds-detail.is-readonly .ds-detail-desc:hover {
      background: transparent;
    }

    .ds-detail.is-readonly .ds-relation-source,
    .ds-detail.is-readonly .ds-relation-local,
    .ds-detail.is-readonly .ds-relation-target {
      border-color: transparent;
      background-color: transparent;
      color: var(--ink);
      appearance: none;
    }

    .ds-relation-local,
    .ds-relation-target {
      text-align: center;
      text-align-last: center;
    }

    .ds-detail.is-readonly .ds-column-description {
      min-height: 0;
      height: auto;
      max-height: none;
      padding: 0;
      overflow: visible;
      field-sizing: content;
      line-height: 1.45;
    }

    .ds-detail.is-readonly .ds-relation-description {
      min-height: 58px;
      max-height: none;
      overflow: visible;
      field-sizing: content;
    }

    .ds-schema-table-wrap { border-color: var(--border-soft); }
    table.ds-schema-table th { border-color: var(--border-soft); }
    table.ds-schema-table td { border-color: var(--border-soft); }

    .ds-schema-name-cell {
      color: var(--ink);
      font-size: 13px;
    }

    .ds-schema-type-cell {
      color: var(--muted);
      font-size: 12px;
    }

    .ds-relation-description {
      padding: 9px 11px;
      font-size: 13px;
      line-height: 1.45;
    }

    .ds-description-technical {
      padding-top: 1.4rem;
      border-top: 1px solid var(--border-soft);
    }

    .ds-technical-grid {
      display: grid;
      grid-template-columns: minmax(0, 1.6fr) minmax(11rem, .7fr) minmax(13rem, .9fr);
      gap: 1rem;
    }

    .ds-technical-field {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: .42rem;
    }

    .ds-technical-input {
      min-height: 38px;
      padding: 9px 12px;
      font-size: 13px;
    }

    .ds-relation-list {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 12px;
    }

    .ds-relation-pair,
    .ds-detail.is-readonly .ds-relation-pair {
      grid-template-columns: minmax(0, 1fr) 18px minmax(0, 1fr);
    }

    .ds-relation-card {
      gap: 12px;
      padding: 16px;
      border: 1px solid var(--border-soft);
      border-radius: var(--r-lg);
      background: var(--surface);
      box-shadow: none;
    }

    .ds-relation-head {
      min-height: 20px;
    }

    .ds-relation-pair {
      gap: 7px;
      padding: 8px 10px;
      border: 1px solid var(--border-soft);
      border-radius: var(--r-md);
      background: var(--surface-inset);
    }

    .ds-relation-pair .ds-relation-equals {
      display: inline-grid;
      place-items: center;
      width: 18px;
      height: 18px;
      align-self: center;
      justify-self: center;
      color: var(--muted);
      font-size: 11px;
      line-height: 1;
    }

    .ds-detail.is-readonly .ds-relation-source {
      padding: 0;
      font-size: 13px;
      font-weight: 600;
      line-height: 1.4;
      text-overflow: ellipsis;
    }

    .ds-detail.is-readonly .ds-relation-local,
    .ds-detail.is-readonly .ds-relation-target {
      padding: 0;
      font-size: 12px;
      line-height: 1.35;
      text-overflow: ellipsis;
    }

    .ds-detail.is-readonly .ds-relation-description {
      min-height: 0;
      margin: 0;
      padding: 10px 0 0;
      border: 0;
      border-top: 1px solid var(--border-soft);
      border-radius: 0;
      background: transparent;
      font-size: 12.75px;
      line-height: 1.5;
    }

    .ds-relation-card:hover,
    .ds-relation-card:focus-within {
      border-color: var(--border-card-hover);
      box-shadow: none;
    }

    .ds-relation-add-card {
      min-height: 168px;
      border-color: var(--border-input);
      border-radius: var(--r-lg);
      color: var(--muted);
      font-size: 13px;
    }

    .ds-relation-add-card:hover {
      border-color: var(--faint);
      background: var(--surface-inset);
      color: var(--ink);
    }

    @media (max-width: 1180px) {
      .ds-detail-heading {
        padding: .9rem 1rem .65rem;
      }
      .ds-detail-title-row { max-width: none; }
      .ds-detail-controls {
        padding: .1rem 1rem .75rem;
      }
      .ds-technical-grid { grid-template-columns: 1fr 1fr; }
      .ds-technical-field:first-child { grid-column: 1 / -1; }
    }

    @media (max-width: 760px) {
      .datasources-body {
        grid-template-columns: minmax(0, 1fr);
      }
      .datasources-sidebar {
        max-height: 17rem;
        border-bottom: 1px solid var(--border);
      }
      .ds-list { height: auto; }
      .ds-detail {
        min-height: 26rem;
        border-top: 0;
        border-left: 0;
      }
      .ds-detail-controls {
        overflow-x: auto;
      }
      .ds-detail-tabs { width: max-content; }
      .ds-relation-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .ds-technical-field { grid-template-columns: 1fr; }
      .ds-technical-grid { grid-template-columns: 1fr; }
      .ds-technical-field:first-child { grid-column: auto; }
    }

    @media (max-width: 520px) {
      .ds-relation-list { grid-template-columns: minmax(0, 1fr); }
    }

    @media (max-width: 720px) {
      .datasources-area { padding: 0; }
      .datasources-wrap { padding: 0; }
      .datasources-body {
        border: 0;
        border-radius: 0;
        box-shadow: none;
      }
      .datasources-sidebar { border-radius: 0; }
    }

    /* Editor panels use the full pane width; description fields sit in
       a balanced two-column grid, technical row spans below. */
    .ds-description-layout {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-template-rows: none;
      align-content: start;
      gap: 20px 26px;
    }

    /* Public descriptions form one compact overview. The panel grows with the
       content; the existing detail pane owns scrolling for long descriptions. */
    .ds-description-layout-readonly {
      display: flex;
      flex-direction: column;
      flex: 0 0 auto;
      align-self: stretch;
      width: min(100%, 1080px);
      height: 100%;
      min-height: 100%;
      max-height: 100%;
      box-sizing: border-box;
      margin-inline: auto;
      gap: 0;
      padding: 0;
      overflow: hidden;
      border: 1px solid var(--border-soft);
      border-radius: var(--r-lg);
      background: var(--surface-inset);
    }

    .ds-dataset-facts {
      display: grid;
      grid-template-columns: minmax(8rem, .65fr) minmax(10rem, .85fr) minmax(10rem, .85fr) minmax(13rem, 1.65fr);
      gap: 1.5rem;
      margin: 0;
      padding: 1.15rem 1.75rem 1.2rem;
    }

    .ds-dataset-footer {
      flex: 0 0 auto;
      margin-top: 0;
      border-top: 1px solid var(--border-soft);
      background: transparent;
    }

    .ds-dataset-footer .ds-workbook-warnings {
      padding: 1rem 1.75rem 0;
    }

    .ds-dataset-fact { min-width: 0; }

    .ds-dataset-fact dt {
      margin: 0 0 .38rem;
      color: var(--muted);
      font-size: 11.5px;
      font-weight: 600;
      line-height: 1.35;
    }

    .ds-dataset-fact dd {
      margin: 0;
      overflow-wrap: anywhere;
      color: var(--ink);
      font-size: 13.5px;
      line-height: 1.45;
    }

    .ds-description-layout-readonly .ds-description-block {
      display: grid;
      flex: 0 0 auto;
      grid-template-columns: minmax(9.5rem, 11.5rem) minmax(0, 1fr);
      gap: 1.6rem;
      min-width: 0;
      min-height: 0;
      box-sizing: border-box;
      padding: 1.35rem 1.75rem 1.45rem;
      overflow: hidden;
      border-bottom: 1px solid var(--border-soft);
      background: transparent;
    }

    .ds-description-layout-readonly .ds-description-summary,
    .ds-description-layout-readonly .ds-description-rules {
      flex: 1 1 0;
    }

    .ds-description-layout-readonly .ds-description-row-meaning {
      flex: 0 0 92px;
    }

    .ds-description-layout-readonly .ds-description-examples {
      flex: 0 0 132px;
    }

    .ds-description-layout-readonly .ds-description-summary .ds-description-copy {
      max-width: 84ch;
      font-size: 15.5px;
      line-height: 1.64;
    }

    .ds-description-layout-readonly .ds-description-summary {
      padding-block: 1.7rem 1.8rem;
      background: transparent;
    }

    .ds-description-layout-readonly .ds-description-summary .ds-detail-section-title {
      color: var(--green-deep);
      font-size: 13px;
    }

    .ds-description-layout-readonly .ds-description-examples {
      border-bottom: 0;
    }

    .ds-description-layout-readonly .ds-detail-section-title {
      margin: .15rem 0 0;
      color: var(--ink);
      font-size: 12.5px;
      font-weight: 650;
      line-height: 1.35;
      letter-spacing: 0;
    }

    .ds-description-copy {
      max-width: 84ch;
      margin: 0;
      color: var(--ink);
      font-size: 14px;
      line-height: 1.68;
      white-space: pre-line;
    }

    .ds-description-scroll {
      min-width: 0;
      min-height: 0;
      max-height: 100%;
      box-sizing: border-box;
      margin-right: -1.75rem;
      padding-right: 0;
      overflow: auto;
      overscroll-behavior: contain;
      scrollbar-width: thin;
      scrollbar-color: var(--scrollbar-thumb-strong) transparent;
    }

    .ds-description-scroll > .ds-description-copy,
    .ds-description-scroll > .ds-example-questions {
      box-sizing: border-box;
      padding-right: 1.75rem;
    }

    .ds-description-scroll:focus-visible {
      border-radius: 2px;
      outline: 2px solid var(--accent);
      outline-offset: 3px;
    }

    .ds-description-scroll::-webkit-scrollbar { width: 7px; height: 7px; }
    .ds-description-scroll::-webkit-scrollbar-track { background: transparent; }
    .ds-description-scroll::-webkit-scrollbar-thumb {
      border-radius: 999px;
      background: var(--scrollbar-thumb-strong);
    }

    .ds-example-questions {
      display: grid;
      gap: .42rem;
      max-width: 84ch;
      margin: 0;
      padding: 0;
      list-style: none;
      color: var(--ink);
      font-size: 14px;
      line-height: 1.58;
    }

    .ds-example-questions li {
      position: relative;
      padding-left: 1rem;
    }

    .ds-example-questions li::before {
      content: '';
      position: absolute;
      top: .7em;
      left: 0;
      width: 4px;
      height: 4px;
      border-radius: 50%;
      background: var(--accent);
    }

    .ds-description-empty {
      color: var(--muted);
      font-style: italic;
    }

    .ds-description-row-meaning,
    .ds-description-rules {
      grid-column: auto;
    }

    .ds-description-technical {
      grid-column: 1 / -1;
      margin-top: 4px;
    }

    @media (max-width: 1100px) {
      .ds-description-layout {
        grid-template-columns: 1fr;
      }

      .ds-description-layout-readonly {
        padding: 0;
      }

      .ds-dataset-facts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }

      .ds-description-layout-readonly .ds-description-block {
        grid-template-columns: 1fr;
        gap: .65rem;
      }

      .ds-description-layout-readonly .ds-description-row-meaning {
        flex-basis: 116px;
      }

      .ds-description-layout-readonly .ds-description-examples {
        flex-basis: 150px;
      }
    }

    @media (max-width: 620px) {
      .ds-dataset-facts { grid-template-columns: 1fr; }
    }

    /* Knihovna: card grid */
    .library-item {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px;
      color: var(--ink);
      box-shadow: var(--shadow-card);
    }

    .library-item:hover {
      background: var(--card-hover-bg);
      border-color: var(--border-card-hover);
      box-shadow: 0 2px 8px rgba(27, 30, 22, .055);
      transform: none;
    }
    /* Ad-hoc chat file attachments */
    .chat-attachments {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      padding: 9px 10px 0;
    }
    .chat-attachments[hidden] { display: none; }
    .chat-attachment-chip {
      position: relative;
      display: grid;
      grid-template-columns: 36px minmax(0, 1fr);
      align-items: center;
      gap: 9px;
      width: min(290px, calc(100vw - 72px));
      min-height: 50px;
      padding: 6px 36px 6px 7px;
      border: 1px solid var(--border);
      border-radius: 11px;
      background: var(--surface);
      color: var(--ink);
      box-sizing: border-box;
      box-shadow: 0 1px 2px rgba(15, 23, 42, .03);
    }
    /* Same treatment as the export-file icon: the drawing carries the type, so
       it is tinted on transparent rather than reversed out of a filled tile. */
    .chat-attachment-icon {
      width: 34px;
      height: 34px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: 0;
      background: transparent;
      color: var(--muted);
    }
    .chat-attachment-chip[data-visual-kind="spreadsheet"] .chat-attachment-icon { color: var(--green); }
    .chat-attachment-chip[data-visual-kind="document"] .chat-attachment-icon { color: var(--blue); }
    .chat-attachment-chip[data-visual-kind="presentation"] .chat-attachment-icon { color: var(--presentation); }
    .chat-attachment-chip[data-visual-kind="pdf"] .chat-attachment-icon { color: var(--red); }
    /* Uploading takes over the icon slot rather than adding a second marker off
       at the edge of the chip: the slot already says what this row is about, and
       the file's own icon takes it back the moment the upload lands. The 36px
       column stays either way, so nothing shifts when it does.

       One ring serves both readings of an upload. Until the browser reports
       anything it is a quarter-arc that turns; once bytes are counted the same
       arc stops and grows to the fraction that has gone out. --upload-progress
       is the arc's length either way, which is why the animated state simply
       leaves it at its initial 25. */
    .chat-attachment-chip.is-uploading .chat-attachment-icon svg { display: none; }
    .chat-attachment-chip.is-uploading .chat-attachment-icon::after {
      content: '';
      width: 19px;
      height: 19px;
      border-radius: 50%;
      background: conic-gradient(
        var(--upload-ring, var(--muted)) calc(var(--upload-progress, 25) * 1%),
        var(--upload-ring-track, color-mix(in srgb, var(--muted) 24%, transparent)) 0);
      /* Masked to a ring rather than drawn as a border: a border cannot be a
         fraction of a circle, and a conic gradient cannot be a border. */
      -webkit-mask: radial-gradient(farthest-side, transparent 76%, #000 78%);
      mask: radial-gradient(farthest-side, transparent 76%, #000 78%);
      animation: spin .8s linear infinite;
      box-sizing: border-box;
    }
    /* Counted bytes: the ring holds still and fills. It stays full and still
       once every byte is out -- the server takes seconds more to store a large
       file, and the only thing that happens next is the file's own icon. */
    .chat-attachment-chip[data-upload-progress] .chat-attachment-icon::after,
    .chat-attachment-chip.is-image[data-upload-progress]::after {
      animation: none;
      transition: --upload-progress .18s linear;
    }
    .chat-attachment-chip.is-error {
      border-color: color-mix(in srgb, var(--red) 35%, var(--border));
    }
    .chat-attachment-chip.is-error .chat-attachment-type { color: var(--red); }
    .chat-attachment-icon svg {
      width: 27px;
      height: 27px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .chat-attachment-copy {
      min-width: 0;
      display: grid;
      gap: 1px;
    }
    .chat-attachment-name {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 13px;
      font-weight: 600;
      line-height: 17px;
    }
    .chat-attachment-type {
      color: var(--muted);
      font-size: 11px;
      line-height: 15px;
    }
    /* The remove button appears on hover, so a chip reads as a file at rest
       rather than as something with a control stuck to it. Kept for keyboard
       users via :focus-within, which hover alone would lock them out of. */
    .chat-attachment-chip { transition: background var(--dur), border-color var(--dur), box-shadow var(--dur); }
    .chat-attachment-chip:hover {
      background: var(--surface-inset);
      border-color: var(--border-card-hover);
      box-shadow: 0 2px 6px rgba(15, 23, 42, .06);
    }
    .chat-attachment-remove {
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--dur), background var(--dur);
      position: absolute;
      /* Straddles the corner rather than sitting inside it, so it reads as a
         badge on the file instead of a control crowding the filename. */
      top: -7px;
      right: -7px;
      display: grid;
      place-items: center;
      width: 20px;
      height: 20px;
      padding: 0;
      /* A ring in the composer's own colour separates it from whatever it
         overlaps. */
      border: 2px solid var(--surface);
      border-radius: 50%;
      background: var(--ink);
      color: var(--on-accent);
      line-height: 0;
      cursor: pointer;
    }
    .chat-attachment-chip:hover .chat-attachment-remove,
    .chat-attachment-chip:focus-within .chat-attachment-remove {
      opacity: 1;
      pointer-events: auto;
    }
    .chat-attachment-remove:hover { background: var(--text); }
    .chat-attachment-remove:focus-visible { opacity: 1; pointer-events: auto; }
    /* An SVG cross centres exactly; the × glyph carries its own side bearings
       and sat a pixel off no matter what line-height it was given. */
    .chat-attachment-remove svg {
      width: 10px;
      height: 10px;
      fill: none;
      stroke: currentColor;
      stroke-width: 2.4;
      stroke-linecap: round;
    }
    #ask-form.is-uploading .chat-attachment-chip {
      border-color: var(--border-card-hover);
      background: var(--surface-inset);
    }
    #ask-form.is-uploading .chat-attachment-remove {
      opacity: 0;
      pointer-events: none;
    }
    .input-wrap.has-attachments:not(.multiline) {
      min-height: 110px;
      border-radius: 24px;
    }
    .input-wrap.has-attachments:not(.multiline) .composer-text-pane {
      min-height: 50px;
      max-height: 50px;
      margin-top: auto;
    }
    .input-wrap.has-attachments:not(.multiline) .composer-footer {
      top: auto;
      bottom: 9px;
      transform: none;
    }
    .chat-drop-overlay {
      position: fixed;
      inset: 0;
      z-index: 9999;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(247, 246, 240, .78);
      backdrop-filter: blur(4px);
      pointer-events: none; /* purely visual; drag events pass through to the window handlers */
    }
    .chat-drop-overlay[hidden] { display: none; }
    .chat-drop-overlay-card {
      min-width: min(360px, calc(100vw - 48px));
      padding: 30px 42px;
      border: 1px dashed var(--border-focus);
      border-radius: var(--r-lg);
      background: rgba(255, 255, 255, .88);
      box-shadow: var(--shadow-pop);
      text-align: center;
      color: var(--ink);
    }
    .chat-drop-overlay-icon {
      width: 38px;
      height: 38px;
      display: grid;
      place-items: center;
      margin: 0 auto;
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--green);
    }
    .chat-drop-overlay-icon svg {
      width: 20px;
      height: 20px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.65;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .chat-drop-overlay-title { margin-top: 12px; font-size: 15px; font-weight: 600; }
    .ds-workbook-warnings {
      display: grid;
      grid-column: 1 / -1;
      gap: 5px;
      padding-bottom: 14px;
    }
    .ds-workbook-warning {
      color: var(--gold);
      font-size: 13px;
      line-height: 1.45;
    }
    .ds-detail-panel.workbook-description.active {
      flex-direction: column;
    }
    .ds-workbook-sheet-nav {
      display: inline-flex;
      align-items: center;
      flex: 0 0 auto;
      gap: 5px;
      margin-left: 12px;
    }
    .ds-workbook-sheet-arrow {
      width: 26px;
      height: 26px;
      flex: 0 0 26px;
      border: 1px solid var(--border-input);
      border-radius: 50%;
      background: var(--surface);
      color: var(--text);
      font-size: 17px;
      line-height: 1;
      cursor: pointer;
    }
    .ds-workbook-sheet-arrow:hover:not(:disabled) {
      background: var(--card-hover-bg);
      border-color: var(--border-card-hover);
    }
    .ds-workbook-sheet-arrow:disabled {
      opacity: .28;
      cursor: default;
    }
    .ds-workbook-sheet-heading {
      display: inline-flex;
      align-items: baseline;
      gap: 6px;
      min-width: 0;
      max-width: 210px;
      color: var(--text);
    }
    .ds-workbook-sheet-heading strong {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-size: 13px;
    }
    .ds-workbook-sheet-heading span {
      color: var(--faint);
      font-size: 12px;
      white-space: nowrap;
    }
    .ds-workbook-area + .ds-workbook-area {
      margin-top: 24px;
    }
    .ds-workbook-area-title {
      margin: 0 0 10px;
      color: var(--text);
      font-size: 13px;
      font-weight: 650;
    }
    .ds-workbook-row-meaning {
      display: grid;
      grid-template-columns: 90px minmax(0, 1fr);
      gap: 12px;
      margin-bottom: 12px;
      color: var(--muted);
      font-size: 12.5px;
      line-height: 1.45;
    }
    .ds-workbook-row-meaning span {
      color: var(--text);
      font-weight: 650;
    }
    .ds-workbook-row-meaning p {
      margin: 0;
    }
    @media (max-width: 760px) {
      .ds-workbook-sheet-nav {
        margin-left: 8px;
      }
    }

    /* Explicit chart command */
    #ask-form {
      flex-direction: column;
    }

    .graph-command-palette,
    .command-palette {
      position: absolute;
      left: 0;
      right: 0;
      bottom: calc(100% + 10px);
      z-index: 120;
      padding: 8px;
      border: 1px solid var(--border-input);
      border-radius: 17px;
      background: rgba(255, 255, 255, .98);
      box-shadow: 0 18px 48px rgba(15, 23, 42, .14);
      backdrop-filter: blur(14px);
    }

    .graph-command-palette[hidden],
    .command-palette[hidden] {
      display: none;
    }

    .graph-command-options,
    .command-palette-options {
      display: grid;
      grid-template-columns: repeat(5, minmax(0, 1fr));
      gap: 8px;
    }

    /* A deck thumbnail is a 16:9 slide, not a 96x54 chart glyph, so the
       template palette runs fewer and wider cells. */
    .command-palette-options.is-templates {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .command-palette-option .template-preview {
      width: 100%;
      aspect-ratio: 16 / 9;
      border-radius: 7px;
      border: 1px solid var(--border-soft);
      overflow: hidden;
      background: var(--surface);
      box-shadow: 0 1px 2px rgba(15, 23, 42, .06);
    }

    .command-palette-option .template-preview svg {
      display: block;
      width: 100%;
      height: 100%;
    }

    /* The thumbnail is the template's own palette at postage-stamp size, so a
       reader picks by recognising the deck rather than by reading its name. */
    .tpl-ground { fill: var(--surface-rail); }
    .tpl-custom { fill: #fff; }
    .tpl-light { fill: #f7f6f0; }
    .tpl-dark { fill: #14160f; }
    .tpl-kicker {
      font-family: var(--font-sans);
      font-size: 5px;
      font-weight: 700;
      letter-spacing: .7px;
    }
    .tpl-heading {
      font-family: var(--font-display);
      font-size: 8px;
      font-weight: 650;
    }
    .tpl-stat {
      font-family: var(--font-sans);
      font-size: 11px;
      font-weight: 700;
    }
    .tpl-source {
      font-family: var(--font-sans);
      font-size: 4px;
    }
    .tpl-grid,
    .tpl-chart {
      fill: none;
      stroke-width: 1;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .tpl-chart { stroke-width: 2; }
    .tpl-neutral { fill: #69706a; }
    .tpl-neutral-strong { fill: #242824; }
    .tpl-neutral-grid { stroke: #e4e7e4; }
    .tpl-neutral-chart { stroke: #69706a; }
    .tpl-neutral-dot { fill: #69706a; }
    .tpl-green { fill: #41702e; }
    .tpl-green-dark { fill: #8eb86b; }
    .tpl-ink { fill: #1b1e16; }
    .tpl-ink-soft-fill { fill: #686b5f; }
    .tpl-paper-fill { fill: #edebdf; }
    .tpl-paper-soft-fill { fill: #b9b6a6; }
    .tpl-light-grid { stroke: #ddded5; }
    .tpl-dark-grid { stroke: #393d32; }
    .tpl-green-chart { stroke: #41702e; }
    .tpl-dark-chart { stroke: #8eb86b; }
    .tpl-mark { fill: #3e9e36; }
    .tpl-mark-dark { fill: #7fb35c; }

    .template-option-copy {
      display: block;
      min-width: 0;
      text-align: left;
    }

    .template-option-copy strong {
      font-size: 12px;
      font-weight: 650;
      color: var(--text);
    }

    .graph-command-option,
    .command-palette-option {
      min-width: 0;
      height: 96px;
      display: grid;
      grid-template-rows: minmax(0, 1fr) auto;
      gap: 5px;
      padding: 9px 9px 8px;
      border: 1px solid transparent;
      border-radius: 11px;
      background: var(--card-hover-bg);
      color: var(--text);
      font-family: var(--font-sans);
      font-size: 12px;
      font-weight: 600;
      cursor: pointer;
      transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
    }

    .command-palette-options.is-templates .command-palette-option {
      height: auto;
      min-height: 150px;
      grid-template-rows: auto auto;
      align-content: start;
      gap: 7px;
    }

    .graph-command-option:hover,
    .graph-command-option:focus-visible,
    .graph-command-option.is-active,
    .command-palette-option:hover,
    .command-palette-option:focus-visible,
    .command-palette-option.is-active {
      border-color: var(--border-card-hover);
      background: var(--active-bg);
      outline: none;
    }

    .graph-command-option:hover,
    .command-palette-option:hover {
      transform: translateY(-1px);
    }

    .graph-command-option svg,
    .command-palette-option svg {
      width: 100%;
      height: 54px;
      overflow: visible;
    }

    /* The chart palette, not the interface greys. charts.js keeps its own set
       for a reason -- it has to hold up as a set, under CVD and against the
       chart surface -- so a preview that used --muted would be advertising a
       chart the app does not draw. Where a token carries the identical value it
       is used; the two grid greys have drifted from theirs, so those are the
       chart's own. */
    .gp-grid {
      fill: none;
      stroke: #e6e3d6;          /* CHART_GRID */
      stroke-width: 1;
    }

    .gp-axis {
      fill: none;
      stroke: #d8d4c3;          /* CHART_RULE */
      stroke-linecap: round;
      stroke-width: 1.2;
    }

    /* Vega interpolates the line as `monotone` and strokes it at 2.1 against a
       54-unit-tall plot, which is what the curve and the weight here are. */
    .gp-line {
      fill: none;
      stroke: var(--accent);
      stroke-linecap: round;
      stroke-linejoin: round;
      stroke-width: 2.4;
    }

    .gp-bar,
    .gp-dot { fill: var(--accent); }

    /* Slices are parted by a surface-coloured stroke, the way the arc mark is
       configured, so the ring reads as separate wedges and not one disc. */
    .gp-slice-0, .gp-slice-1, .gp-slice-2, .gp-slice-3 {
      stroke: var(--surface);
      stroke-width: 1.6;
    }
    .gp-slice-0 { fill: var(--accent); }
    .gp-slice-1 { fill: var(--blue); }
    .gp-slice-2 { fill: var(--gold); }
    .gp-slice-3 { fill: #8043a6; }   /* flax violet, slot 4 -- no UI token */

    /* A choropleth in the `blues` scheme the map layer asks Vega for, on the
       app's own kraje outlines, hairlined in the chart surface. */
    .graph-command-option [class^="gp-map-"] {
      stroke: var(--surface);
      stroke-width: .5;
      stroke-linejoin: round;
    }
    .gp-map-0 { fill: #deebf7; }
    .gp-map-1 { fill: #c6dbef; }
    .gp-map-2 { fill: #9ecae1; }
    .gp-map-3 { fill: #6baed6; }
    .gp-map-4 { fill: #4292c6; }
    .gp-map-5 { fill: #2171b5; }

    @media (max-width: 680px) {
      .graph-command-palette,
      .command-palette {
        left: 8px;
        right: 8px;
      }

      .graph-command-options,
      .command-palette-options {
        grid-auto-flow: column;
        grid-auto-columns: 126px;
        grid-template-columns: none;
        overflow-x: auto;
        overscroll-behavior-inline: contain;
        scroll-snap-type: inline proximity;
      }

      .graph-command-option {
        scroll-snap-align: start;
      }

      .command-palette-options.is-templates {
        grid-template-columns: none;
        grid-auto-columns: 210px;
      }

      .command-palette-options.is-templates .command-palette-option {
        scroll-snap-align: start;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .graph-command-option {
        transition: none;
      }
    }

    /* Databáze: two screens rather than two columns well before phone width.
       The rail and the catalogue are both fixed, so the source column takes
       whatever is left -- at 1100px that is already down to a 514px measure,
       and by 900 it is 335px, which is a column of two-word lines. Below the
       switch the catalogue gets a screen and the source gets a screen, with a
       way back. */
    @media (max-width: 1100px) {
    /* Two columns do not fit, and squeezing them gave a five-row list above
       a screenful of "choose from the list on the left" -- with no left to
       choose from. They are two screens instead: the catalogue, then the
       source, with a way back. */
    .datasources-body {
      display: block;
      position: relative;
      height: auto;
      max-height: none;
      overflow: visible;
    }

    .datasources-sidebar,
    .ds-detail {
      width: 100%;
      max-width: none;
      border: 0;
    }

    /* The 1100px breakpoint caps the list at 260px so it can sit above the
       detail. Here they are separate screens, so the catalogue gets the
       whole of one. */
    .ds-list {
      max-height: none;
      height: auto;
      overflow-y: visible;
    }

    /* A narrower breakpoint caps the sidebar so it can sit above the detail
       in one scroller. Here it is the whole screen, so the cap has to go or
       the catalogue shows five of its 133 rows. */
    .datasources-wrap,
    .datasources-sidebar {
      height: auto;
      max-height: none;
      overflow: visible;
    }

    .datasources-area {
      overflow-y: auto;
    }

    body:not(.ds-detail-open) .ds-detail,
    body:not(.ds-detail-open) .ds-detail-back {
      display: none;
    }

    body.ds-detail-open .datasources-sidebar {
      display: none;
    }

    .ds-detail-back {
      display: none;
      align-items: center;
      gap: 6px;
      margin: 0 0 4px;
      padding: 8px 12px 8px 4px;
      border: 0;
      background: transparent;
      color: var(--accent);
      font: inherit;
      font-size: 14px;
      font-weight: 550;
      cursor: pointer;
    }

    body.ds-detail-open .ds-detail-back {
      display: inline-flex;
    }

    .ds-detail-back svg {
      width: 18px;
      height: 18px;
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    }

    /* ── Independent news timeline and daily brief ─────────── */
    .zpravy-wrap {
      max-width: none;
      padding-top: 0;
    }

    /* One view at a time, the way the phone has always done it: the brief is a
       column of prose and the articles are a list, and side by side neither got
       the width it wanted. The header carries the choice between them, which is
       also what gives a header with two controls something to be. */
    .zpravy-layout {
      /* One measure for the header and the column under it, so the title, the
         controls and the prose share their edges. */
      --zpravy-measure: var(--section-measure);
      grid-template-columns: minmax(0, 1fr);
      grid-template-rows: auto minmax(0, 1fr);
      column-gap: 0;
      row-gap: 0;
      align-items: stretch;
    }

    /* Both at once where there is room: .zpravy-main is the article feed and
       .zpravy-side is the brief -- the names read the other way round than they
       behave. The phone still shows one at a time. */
    .zpravy-main { min-width: 0; }
    .zpravy-side { min-width: 0; }

    /* A reading measure, centred, rather than a column pinned to the left edge. */
    /* The page scrolls as one, header included: the brief is a document, and
       pinning a header above an inner scroller meant two things to scroll and a
       band of chrome that never went away. */
    /* No top padding: the bookmark hangs from the very top, and a gap above it
       reads as an empty row. */
    .zpravy-area {
      overflow-y: auto;
      padding-top: 0;
      /* The gutter is held whether or not the day's articles overflow, so
         paging between days does not nudge both columns sideways. */
      scrollbar-gutter: stable;
    }

    .zpravy-wrap,
    .zpravy-layout { height: auto; min-height: 0; }

    .news-brief-scroll,
    .zpravy-scroll {
      flex: 0 0 auto;
      min-height: 0;
      max-height: none;
      overflow: visible;
      /* The right gutter existed so the old inner scrollbar could reach the
         window edge past the cards. The page scrolls as one now, and that
         one-sided inset was throwing the centred feed 12px off the header. */
      padding-right: 0;
    }

    .zpravy-main,
    .zpravy-side { height: auto; }

    /* The columns span the area and the measure sits on what they hold. */
    .zpravy-main,
    .zpravy-side {
      width: 100%;
      margin: 0;
    }

    #news-brief-content,
    #zpravy-feed {
      width: 100%;
      max-width: var(--zpravy-measure);
      margin: 0 auto;
    }

    /* The header sat against the top edge with a small caption for a title, which
       is most of why it read as a toolbar rather than a page. It now opens with
       room above it and a title at display size, with the day controls on that
       same line and the view tabs under them -- the shape both of the apps this
       was measured against use, and the shape that gives a header with two
       controls something to be. */
    /* A row, laid out as one. The grid this used to be carried placements from
       the two-column design on every child, and empty tracks kept sizing
       themselves from them. */
    /* A sticker rather than a bar: the header is a small upright card parked in
       the margin beside the column, so the reading width and the full height
       both belong to the text and the controls still travel with the reader. */
    /* Two columns: the bookmark sits at the top of the left one with the
       articles running under it, and the brief takes the right the whole way
       down. */
    .zpravy-layout {
      display: grid;
      grid-template-columns: minmax(300px, 0.8fr) minmax(0, 1.2fr);
      align-items: start;
      gap: 28px;
    }

    /* The articles' header: the section name and the day on one line, on the
       same surface as the cards under it so the column reads as one stack. */
    .zpravy-toolbar {
      flex: 0 0 auto;
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: 14px;
      width: 100%;
      margin: 0;
      padding: 10px 16px 10px 18px;
      border: 1px solid var(--border);
      border-radius: var(--r-lg);
      background: var(--surface);
      box-shadow: none;
    }

    /* The card hung off the top edge and wanted none of this; a plain heading
       needs the room above it that every other section's has. */
    .zpravy-wrap { padding-top: 28px; }

    /* The date takes its own line so the arrows keep full size: squeezed onto one
       row inside a 196px card they shrank to 24px, which is the complaint this
       whole cluster started from. */
    .news-brief-nav {
      /* Pulled back by the first button's own padding so the arrow lines up
         with the title above it rather than its tap target's edge. */
      margin: 0 0 0 -10px;
      padding-top: 0;
      border-top: 0;
      width: auto;
      gap: 2px;
      flex-wrap: nowrap;
      justify-content: flex-start;
    }

    /* Back on the arrows' line now the card is wide enough to hold all three at
       full size -- on its own row it left them stranded at the card's edges. */
    .news-brief-date {
      order: 0;
      /* Reserved rather than fitted: "3.8. - pondeli" and "29.8. - sobota" are
         different widths, and sized to their content each day would shift the
         arrows and everything after them. Wide enough for the longest -- a
         two-digit day in a two-digit month with the longest weekday. */
      width: 9.5rem;
      justify-content: center;
      height: auto;
      padding: 0 2px;
      font-size: 14px;
    }

    .news-brief-nav-btn { flex: 0 0 auto; }

    .news-brief-nav {
      grid-column: auto;
      grid-row: auto;
      margin-left: auto;
    }

    /* Above the phone breakpoint the day sits with the title rather than at the
       far end of the band: the two name what is being read, and split apart
       they read as two controls. The auto margin above is the phone's. */
    @media (min-width: 721px) {
      .news-brief-nav { margin-left: 0; }

      /* The rail already names this section, so the band carries only the day
         and the filter. Still a heading for anything reading the page -- it is
         taken out of the layout, not out of the document. */
      .zpravy-title {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        border: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
      }
    }

    .zpravy-title {
      display: flex;
      align-items: baseline;
      gap: 10px;
      grid-column: auto;
      grid-row: auto;
      /* The section's name is not what gives way when the band is tight -- it
         used to shrink, and clipped itself to "Zp". The filter beside it takes
         the squeeze instead. */
      flex: 0 0 auto;
      margin: 0;
      font-family: var(--font-display);
      font-size: 27px;
      font-weight: 400;
      line-height: 1.15;
      letter-spacing: -.015em;
      white-space: nowrap;
    }

    .zpravy-side-controls {
      /* Its own line, after the title row, and only with the articles. */
      grid-column: auto;
      grid-row: auto;
      width: 100%;
      flex-direction: row;
      align-items: center;
      justify-content: flex-end;
      gap: 10px;
      width: auto;
      margin: 0;
      padding: 0;
      border: 0;
    }

    .zpravy-main,
    .zpravy-side {
      min-width: 0;
      min-height: 0;
    }

    /* The bookmark is the top of this column, not a band across both, so the
       articles begin directly under it rather than beside it. */
    .zpravy-main { padding: 0; }

    /* The brief runs the full height alongside, so it starts level with the
       bookmark rather than below it. No right padding: the scroller has to
       reach the column's rule so its thumb rides against it instead of hanging
       in the gap. */
    .zpravy-side {
      position: static;
      max-height: none;
      gap: 0;
      padding: 0;
      /* The divider separated this column from the articles beside it; the
         column gap does that work now. */
      border-right: 0;
    }

    .zpravy-side-controls {
      /* Its own line, after the title row, and only with the articles. */
      grid-column: auto;
      grid-row: auto;
      width: 100%;
      flex: 0 0 auto;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      gap: 8px;
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      background: transparent;
      box-shadow: none;
    }
    /* An export gets into Zprávy by being dropped on the tab, so there is no
       upload control at rest -- the header carries the day, not a button nobody
       presses. It appears as the status of a drop instead: a ring while the
       export uploads and ingests, the reason in red if it does not go through,
       and gone again once the day is in the feed. Non-admins never see it at
       all; `base.css` hides it with `!important` and that still wins. */
    .zpravy-upload-btn {
      display: none;
      min-height: 38px;
      padding: 8px 13px;
      border-color: var(--border-input);
      background: var(--surface);
      color: var(--text);
      white-space: nowrap;
    }

    .zpravy-upload-btn:hover {
      border-color: var(--border-focus);
      background: var(--surface-page);
      color: var(--ink);
    }

    /* The status says what is happening beside the ring rather than instead of
       it: this is only on screen while a drop is being processed or has failed,
       so there is no resting width to preserve and no reason to make a bare
       spinner carry the message. The shared ring is white-on-dark, so it is
       re-tinted for this light surface. */
    .zpravy-upload-btn.is-busy,
    .zpravy-upload-btn.is-error {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
    }

    .zpravy-upload-btn .btn-loading-ring {
      display: none;
      flex: 0 0 auto;
      border-color: rgba(39, 50, 68, .22);
      border-top-color: #273244;
    }

    .zpravy-upload-btn.is-busy { cursor: progress; }
    .zpravy-upload-btn.is-busy .btn-loading-ring { display: block; }

    .zpravy-upload-btn.is-error,
    .zpravy-upload-btn.is-error:hover {
      border-color: var(--red);
      background: var(--card-hover-bg);
      color: var(--red);
    }

    /* One cluster, not two arrows at opposite ends of the header. The middle
       column used to be 1fr, which stretched the date to 500px and left the two
       controls that belong together 554px apart -- each a 34px circle. Sized to
       its content, the three sit within a thumb's travel of each other. */
    .news-brief-nav {
      position: relative;
      flex: 0 0 auto;
      display: inline-flex;
      align-items: center;
      gap: 2px;
      min-height: 40px;
      padding: 0;
    }

    .news-brief-date {
      display: inline-flex;
      align-items: center;
      max-width: 22rem;
      height: 40px;
      padding: 0 6px;
      color: var(--ink);
      font-size: 15px;
      font-weight: 500;
      line-height: 20px;
      white-space: nowrap;
    }

    /* Grid centring plus an SVG chevron: the ‹ › glyphs sat off-centre in the
       circle because they align to the text baseline, not the button box. */
    .news-brief-nav-btn {
      width: 40px;
      height: 40px;
      display: grid;
      place-items: center;
      padding: 0;
      border: 0;
      border-radius: 50%;
      background: transparent;
      color: var(--muted);
      cursor: pointer;
      transition: background-color .15s ease, color .15s ease;
    }

    .news-brief-nav-btn svg {
      width: 20px;
      height: 20px;
      fill: none;
      stroke: currentColor;
      stroke-width: 2;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .news-brief-nav-btn:hover:not(:disabled) {
      background: var(--hover-bg);
      color: var(--ink);
    }

    .news-brief-nav-btn:disabled {
      color: var(--faint);
      cursor: default;
    }

    /* Not a scroller any more -- the page scrolls as one. Left as `auto` it kept
       the wheel: an overflow box that cannot scroll still swallows the event,
       and `overscroll-behavior: contain` stopped it chaining out to the page, so
       the brief would not move at all while the articles did. */
    .news-brief-scroll {
      flex: 0 0 auto;
      min-height: 0;
      overflow: visible;
      overscroll-behavior: auto;
    }

    .news-brief-content {
      width: 100%;
      min-height: 100%;
      /* 42px on the right = the brief's own 18px plus the 24px the column used
         to hold, so the text sits where it did and only the thumb moved. */
      padding: 18px 42px 56px 18px;
    }

    .news-brief-message {
      max-width: var(--content-width);
    }

    .news-brief-message .answer-text {
      padding-top: 0;
    }

    .news-brief-message .answer-text > h1:first-child {
      margin-top: 0;
    }

    /* A skeleton, not a ring. A spinner that appears for a moment and vanishes
       reads as a glitch; lines that fade in where the text will be read as the
       page still settling. Same shimmer as the chat and the library. */
    .news-brief-loading {
      display: grid;
      gap: 10px;
      align-content: start;
      padding: 6px 2px;
    }

    .news-brief-loading span {
      display: block;
      height: 12px;
      border-radius: 999px;
      background: var(--skeleton);
      background-size: 220% 100%;
      animation: subtleSkeleton 1.9s ease-in-out infinite;
    }

    .news-brief-loading span:nth-child(2) { width: 82%; animation-delay: .12s; }
    .news-brief-loading span:nth-child(3) { width: 64%; animation-delay: .24s; }

    .news-brief-empty {
      max-width: var(--content-width);
      margin: 54px auto 0;
      color: var(--muted);
      font-size: 14px;
      text-align: center;
    }

    /* Two columns for as long as they fit; below that the brief and the article
       feed become two screens rather than one stacked under the other. Stacked,
       the feed began below a brief the height of the window -- a place nobody
       scrolls to -- and the filter and upload controls sat up top belonging to
       neither of them.

       1119px is where the two columns stop fitting: the grid's own minimums
       (520 + 340) plus the rail and the page padding come to 1120, and below
       that the feed column ran off the right of the window. */
    @media (max-width: 1119px) {
      /* No bottom padding: it is a dead band the scroller cannot reach, so the
         last line of the brief was clipped by empty page rather than running to
         the edge. The breathing room lives inside the scrollers instead. */
      .zpravy-area {
        overflow: hidden;
        padding-right: var(--main-pad);
        padding-bottom: 0;
      }

      .zpravy-wrap,
      .zpravy-layout {
        height: 100%;
        min-height: 0;
      }

      .zpravy-layout {
        grid-template-columns: 1fr;
        grid-template-rows: auto minmax(0, 1fr);
      }

      .zpravy-toolbar {
        grid-column: 1;
        grid-row: 1;
        grid-template-columns: 1fr;
      }

      .news-brief-nav {
        padding: 0;
        border-right: 0;
      }

      .zpravy-side-controls {
        grid-column: 1;
        grid-row: 2;
        padding: 0 0 10px;
      }

      /* Bled to the right edge: the scroller has to reach it for its bar to sit
         against the window rather than float inside. The reading inset moves off
         the column and onto the content, so the text keeps its margin. */
      .zpravy-side,
      .zpravy-main {
        grid-column: 1;
        grid-row: 2;
        min-height: 0;
        margin-right: calc(var(--main-pad) * -1);
        padding: 0;
        border-right: 0;
      }

      .news-brief-scroll,
      .zpravy-scroll {
        min-height: 0;
        max-height: none;
      }

      /* The two-column brief carries an extra 24px on the right for the rule it
         sits beside. There is no rule here, and on a phone that asymmetry is a
         sixth of the screen. */
      .news-brief-content {
        padding: 10px var(--main-pad) 40px 0;
      }

      .zpravy-scroll {
        padding: 0 var(--main-pad) 40px 0;
      }

    }

    @media (prefers-reduced-motion: reduce) {
      .news-brief-nav-btn {
        transition: none;
      }

      body[data-mode="zpravy"] .zpravy-view-tab {
        transition: none;
      }

      body[data-mode="zpravy"] .zpravy-side,
      body[data-mode="zpravy"] .zpravy-main {
        animation: none;
      }
    }

    /* Shown when an answer promised a chart the renderer could not accept. */
    .sources-note {
      margin: 0 0 10px;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.5;
    }

    .answer-interruption-note {
      color: var(--muted);
      font-size: 13px;
    }

    .answer-visualization-note {
      margin: 10px 0 2px;
      padding: 10px 12px;
      border: 1px solid var(--border-soft);
      border-radius: var(--r-md);
      background: var(--surface-inset);
      color: var(--muted);
      font-size: 13px;
      line-height: 1.5;
    }

    /* Files shown with the message that carried them. Sits under the bubble so
       the text keeps its own shape, and reads as a caption rather than a second
       message. */
    /* One row per file, stacked above the bubble and aligned with it. */
    .message-attachments {
      /* Spans the message so the rows have a width to size against; without it
         the column shrink-wraps and their percentage resolves to nothing. */
      align-self: stretch;
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      gap: 8px;
      margin-bottom: 8px;
    }
    .message-attachment {
      display: flex;
      align-items: center;
      gap: 10px;
      width: min(320px, 75%);
      padding: 9px 12px;
      border: 1px solid var(--border-soft);
      border-radius: var(--r-lg, 12px);
      background: var(--surface);
      box-shadow: var(--shadow-card, 0 1px 2px rgba(15, 23, 42, .04));
      color: inherit;
      text-decoration: none;
      transition: background var(--dur), border-color var(--dur), box-shadow var(--dur);
    }
    /* It opens, so it behaves like something that opens. */
    a.message-attachment { cursor: pointer; }
    a.message-attachment:hover {
      background: var(--surface-inset);
      border-color: var(--border-card-hover);
      box-shadow: 0 3px 10px rgba(15, 23, 42, .08);
    }
    a.message-attachment:focus-visible {
      outline: 2px solid var(--green);
      outline-offset: 2px;
    }

    /* An image shows itself rather than a row about itself. */
    .message-attachment.is-image {
      width: auto;
      max-width: min(320px, 75%);
      padding: 0;
      overflow: hidden;
    }
    .message-attachment-preview {
      display: block;
      width: 100%;
      max-height: 260px;
      object-fit: cover;
    }
    /* Name over type, the way the composer chip reads. */
    .message-attachment-copy {
      display: flex;
      flex-direction: column;
      min-width: 0;
      gap: 1px;
    }
    .message-attachment-icon {
      flex: 0 0 auto;
      display: inline-grid;
      place-items: center;
      color: var(--muted);
    }
    .message-attachment-icon svg {
      width: 26px;
      height: 26px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.6;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
    .message-attachment[data-visual-kind="spreadsheet"] .message-attachment-icon { color: var(--green); }
    .message-attachment[data-visual-kind="document"] .message-attachment-icon { color: var(--blue); }
    .message-attachment[data-visual-kind="presentation"] .message-attachment-icon { color: var(--presentation); }
    .message-attachment[data-visual-kind="pdf"] .message-attachment-icon { color: var(--red); }
    .message-attachment-name {
      min-width: 0;
      overflow: hidden;
      color: var(--ink);
      font-size: 13px;
      font-weight: 600;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .message-attachment-type {
      color: var(--faint);
      font-size: 12px;
    }

    /* An image attachment is a thumbnail, not a chip: the picture identifies it
       far better than its filename, and at chip width it would otherwise be
       stretched across the whole tray. */
    .chat-attachment-chip.is-image {
      display: block;
      width: 52px;
      min-width: 52px;
      height: 52px;
      min-height: 52px;
      padding: 0;
      border-radius: 11px;
    }
    /* A thumbnail is the image's own icon, so the ring takes that slot the same
       way -- over the picture, which dims to let it read. */
    .chat-attachment-chip.is-image.is-uploading::after {
      content: '';
      position: absolute;
      inset: 17px;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: conic-gradient(
        #fff calc(var(--upload-progress, 25) * 1%),
        rgba(255, 255, 255, .4) 0);
      -webkit-mask: radial-gradient(farthest-side, transparent 76%, #000 78%);
      mask: radial-gradient(farthest-side, transparent 76%, #000 78%);
      animation: spin .8s linear infinite;
      box-sizing: border-box;
      filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .35));
    }
    .chat-attachment-chip.is-image.is-uploading .chat-attachment-thumb { opacity: .6; }
    /* The thumbnail rounds itself, so the chip need not clip -- clipping would
       cut the remove badge off at the corner it straddles. */
    .chat-attachment-thumb {
      display: block;
      width: 100%;
      height: 100%;
      border-radius: 10px;
      object-fit: cover;
    }

    /* The catalogue and a source are one screen with two columns everywhere
       but a phone, so there is nothing to go back to and no button for it. */
    .ds-detail-back {
      display: none;
    }

    /* ── Portrait ─────────────────────────────────────────────────────────
       The rail toggle is fixed in the top-left corner and floats over
       whatever is underneath, which on a phone is always the first control of
       the view: the Knihovna title, the previous-day arrow, the catalogue
       search. Nothing reserved room for it, so it sat on top of them.

       One variable holds the room it needs, and each view's first row keeps
       clear of it. */
    @media (max-width: 720px) {
      /* The rail control floats just above the active bottom controls. It no
         longer consumes an otherwise empty first row in every phone view. */
      .mobile-rail-toggle {
        top: auto;
        left: auto;
        right: calc(12px + env(safe-area-inset-right, 0px));
        bottom: calc(14px + env(safe-area-inset-bottom, 0px));
      }

      body[data-mode="library"] .mobile-rail-toggle,
      body[data-mode="zpravy"] .mobile-rail-toggle {
        bottom: calc(76px + env(safe-area-inset-bottom, 0px));
      }

      body[data-mode="datasources"] .mobile-rail-toggle {
        bottom: calc(65px + env(safe-area-inset-bottom, 0px));
      }

      body[data-mode="chat"] .mobile-rail-toggle {
        bottom: calc(84px + env(safe-area-inset-bottom, 0px));
      }

      /* On a phone these are thumb controls, so they sit below the content.
         The rail toggle remains at the top and the lists reserve just enough
         room for it instead of repeating the current section as a title. */
      .library-area {
        padding-top: 0;
        padding-bottom: 0;
        overflow: hidden;
      }

      .library-wrap {
        height: 100%;
        min-height: 0;
        display: flex;
        flex-direction: column;
      }

      .library-toolbar-shell {
        position: static;
        order: 2;
        flex: 0 0 auto;
        margin: 0 calc(var(--main-pad) * -1);
        padding: 10px var(--main-pad) calc(10px + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--border-soft);
        border-bottom: 0;
        background: rgb(var(--surface-page-rgb) / .96);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
      }

      .library-list {
        order: 1;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        align-content: start;
        /* Let the native scroll track sit on the phone edge while preserving
           the same inset for the cards themselves. */
        margin-inline: calc(var(--main-pad) * -1);
        padding-inline: var(--main-pad);
        padding-top: 12px;
        padding-bottom: 18px;
      }

      .zpravy-area {
        padding-top: 0;
      }

      .library-toolbar {
        flex-direction: row;
        flex-wrap: nowrap;
        align-items: center;
        gap: 10px;
        padding: 0;
      }

      /* The heading used to be dead weight on a phone and was hidden. It now
         carries the category filter, so it has to stay -- shrunk to sit in the
         bottom bar beside the search field, and capped so it yields space to
         it rather than squeezing it out. */
      .library-toolbar-copy {
        display: block;
        min-width: 0;
        flex: 0 1 auto;
      }

      .library-title {
        display: block;
        font-size: 16px;
        letter-spacing: -.01em;
      }

      .library-title-btn {
        gap: 6px;
        max-width: 42vw;
        margin-inline-start: -8px;
        padding: 7px 8px;
      }

      .library-title-btn .ds-type-dd-chev {
        width: 14px;
        height: 14px;
      }

      /* Tighter on a phone, where the whole column is the measure. */
      .library-section + .library-section {
        margin-top: 22px;
        padding-top: 22px;
      }

      .library-toolbar-actions {
        width: auto;
        /* Widened for the category dropdown: at the old 328px the search field
           was squeezed to a stub once the filter sat beside it. */
        max-width: none;
        min-width: 0;
        flex: 1 1 auto;
        margin-left: 0;
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        align-items: center;
        gap: 8px;
      }

      /* The wider breakpoint gives the filter a 100% basis, which on a wrapping
         row puts the button on a line of its own. */
      .library-toolbar-actions .library-filter {
        width: auto;
        flex: 1 1 auto;
        max-width: none;
        min-width: 0;
      }

      /* On the desktop row the upload button leads, so the search field and the
         category filter finish against the edge. The phone row wraps the search
         onto its own line, where the button belongs beside the filter instead. */
      .library-toolbar-actions .library-upload-btn {
        flex: 0 0 auto;
        order: 1;
      }

      /* Databáze is one phone workspace. The selected source fills the screen
         and the bottom field opens the catalogue upward like a compact picker. */
      .datasources-area,
      .datasources-wrap,
      .datasources-body {
        height: 100%;
        min-height: 0;
      }

      .datasources-area {
        overflow: hidden;
      }

      /* Phone users swipe the table itself. The separate desktop drag control
         costs a full row of scarce preview height and adds no touch value. */
      .ds-sheet-scrollbar {
        display: none;
      }

      .datasources-body {
        --ds-mobile-control-height: calc(59px + env(safe-area-inset-bottom, 0px));
        --ds-mobile-detail-controls-height: 50px;
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: minmax(0, 1fr) auto;
        position: relative;
        overflow: hidden;
      }

      .datasources-sidebar,
      body.ds-detail-open .datasources-sidebar {
        display: contents;
      }

      .ds-detail,
      body:not(.ds-detail-open) .ds-detail {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-rows: auto minmax(0, 1fr) auto;
        grid-column: 1;
        grid-row: 1;
        width: 100%;
        height: auto;
        min-height: 0;
        overflow: hidden;
      }

      .ds-detail-header {
        display: contents;
      }

      .ds-detail-heading {
        grid-column: 1 / -1;
        grid-row: 1;
        padding: 14px 16px 12px;
        border-bottom: 1px solid var(--border-soft);
      }

      .ds-detail-content {
        grid-column: 1 / -1;
        grid-row: 2;
      }

      /* On a phone the detail pane is the page. Its description therefore
         owns one continuous scroll instead of presenting four small nested
         scrollports followed by an oversized facts footer. */
      .ds-detail-content:has(.ds-detail-panel[data-detail-panel="description"].active) {
        padding: 0 0 18px;
      }

      .ds-detail-content:has(.ds-detail-panel[data-detail-panel="schema"].active) {
        padding-top: 0;
      }

      .ds-detail-panel[data-detail-panel="description"].active {
        display: block;
        min-height: 0;
      }

      .ds-description-layout-readonly {
        width: 100%;
        height: auto;
        min-height: 0;
        max-height: none;
        margin: 0;
        overflow: visible;
        border-right: 0;
        border-left: 0;
        border-radius: 0;
      }

      .ds-description-layout-readonly .ds-description-block,
      .ds-description-layout-readonly .ds-description-summary,
      .ds-description-layout-readonly .ds-description-row-meaning,
      .ds-description-layout-readonly .ds-description-rules,
      .ds-description-layout-readonly .ds-description-examples {
        flex: none;
        min-height: 0;
        overflow: visible;
      }

      .ds-description-layout-readonly .ds-description-row-meaning,
      .ds-description-layout-readonly .ds-description-examples {
        flex-basis: auto;
      }

      .ds-description-layout-readonly .ds-description-scroll {
        max-height: none;
        margin-right: 0;
        overflow: visible;
      }

      .ds-description-layout-readonly .ds-description-scroll > .ds-description-copy,
      .ds-description-layout-readonly .ds-description-scroll > .ds-example-questions {
        padding-right: 0;
      }

      /* Four table columns become too narrow on a phone. The schema keeps its
         table semantics, but each data row uses the full viewport: identity
         and type stay compact above a full-width description. */
      .ds-detail-panel[data-detail-panel="schema"].active .ds-schema-table-wrap {
        margin-inline: calc(-1 * clamp(1.55rem, 2.4vw, 2.2rem));
        border-right: 0;
        border-left: 0;
        border-radius: 0;
      }

      .ds-detail-panel[data-detail-panel="schema"] table.ds-schema-table {
        display: block;
        table-layout: auto;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table colgroup {
        display: none;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody {
        display: block;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto auto;
        gap: .25rem .75rem;
        padding: .75rem var(--main-pad);
        border-bottom: 1px solid var(--border-soft);
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody tr:last-child {
        border-bottom: 0;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody td {
        display: block;
        padding: 0;
        border-bottom: 0;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody td:nth-child(2),
      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody td:nth-child(3) {
        color: var(--muted);
        font-size: .7rem;
        text-align: right;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody td:nth-child(3):empty {
        display: none;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-schema-table tbody td:nth-child(4) {
        grid-column: 1 / -1;
        padding-top: .2rem;
      }

      .ds-detail-panel[data-detail-panel="schema"] .ds-column-unit {
        width: min(6rem, 22vw);
      }

      .ds-detail-controls {
        display: contents;
      }

      .ds-detail-tabs {
        grid-column: 1 / -1;
        grid-row: 3;
        width: 100%;
        min-height: var(--ds-mobile-detail-controls-height);
        box-sizing: border-box;
        padding: 7px 112px 8px 16px;
        border-top: 1px solid var(--border-soft);
        background: rgb(var(--surface-page-rgb) / .96);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
      }

      .ds-detail-actions {
        grid-column: 2;
        grid-row: 3;
        align-self: center;
        justify-self: end;
        margin-left: 0;
        margin-right: 62px;
        padding: 0;
        z-index: 2;
      }

      .ds-detail-actions .ds-detail-download {
        width: 38px;
        min-height: 38px;
        padding: 0;
        border-radius: 11px;
      }

      .ds-detail-actions .ds-detail-download span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
      }

      .ds-detail-actions:empty {
        display: none;
      }

      .ds-detail-back,
      body.ds-detail-open .ds-detail-back {
        display: none;
      }

      .datasources-sidebar-controls {
        position: static;
        grid-column: 1;
        grid-row: 2;
        flex: 0 0 auto;
        z-index: 50;
        flex-direction: row;
        align-items: center;
        gap: 8px;
        min-height: 0;
        padding: 10px var(--main-pad) calc(10px + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--border-soft);
        border-bottom: 0;
        background: rgb(var(--surface-page-rgb) / .96);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
      }

      .datasources-sidebar-title {
        display: none;
      }

      .datasources-sidebar-controls .ds-search-row {
        width: 100%;
        flex: 1 1 auto;
        max-width: none;
        min-width: 0;
        margin-left: auto;
      }

      .ds-list,
      body:not(.ds-detail-open) .ds-list {
        position: absolute;
        z-index: 55;
        left: var(--main-pad);
        right: var(--main-pad);
        bottom: calc(var(--ds-mobile-control-height) + var(--ds-mobile-detail-controls-height) + 6px);
        display: none;
        max-height: min(52vh, 420px);
        height: auto;
        overflow-y: auto;
        padding: 6px;
        border: 1px solid var(--border);
        border-radius: var(--r-lg);
        background: var(--surface);
        box-shadow: var(--shadow-pop);
      }

      body.ds-mobile-picker-open .ds-list {
        display: flex;
      }

      body.ds-mobile-picker-open .ds-filter {
        border-color: var(--border-focus);
      }

      .ds-list .catalog-empty {
        padding: 18px 12px;
      }

      .zpravy-toolbar {
        position: static;
        grid-row: 2;
        z-index: 50;
        border-top: 1px solid var(--border-soft);
        border-bottom: 0;
        background: rgb(var(--surface-page-rgb) / .96);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
      }

      .zpravy-layout {
        grid-template-rows: minmax(0, 1fr) auto;
      }

      .zpravy-side,
      .zpravy-main {
        grid-row: 1;
      }

      .news-brief-content {
        padding-top: 18px;
      }

      .zpravy-scroll {
        padding-top: 10px;
      }

      .ds-detail-back {
        margin-left: 0;
      }

      /* Chat: the composer belongs at the bottom of a phone, under the thumb.
         Centring it is a desktop conceit -- there the empty state is a poster,
         here it is a keyboard away. The screen then reads top to bottom the way
         the hand works it: greeting up top, examples within reach, the thing you
         type in last and lowest. */
      body.chat-empty #input-area {
        top: auto;
        bottom: 0;
        /* Not flush against the edge: a composer touching the bezel reads as
           cut off, and on a phone with a home indicator it is also under it. */
        padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
        display: flex;
        /* The suggestions follow the form in the markup, which is right on a
           desktop and upside down here. Reversing the column lifts them above
           the composer without moving anything in the DOM, so the tab order
           still runs composer-first. */
        flex-direction: column-reverse;
        align-items: stretch;
      }

      /* The form centres itself with auto margins, and an auto margin turns off
         a flex item's stretch -- so as soon as the row above became a flex
         container the composer collapsed to the width of its own buttons. */
      body.chat-empty #input-area form {
        width: 100%;
      }

      /* Each row is now a tap target sitting right under the thumb, so they get
         a little more height than the desktop list and stop just short of the
         composer. */
      /* The gap has to beat the spacing between the rows themselves, or the
         composer reads as a fifth row of the list rather than the thing the
         examples are examples for.

         Qualified by #input-area to outrank the desktop rule: type.css imports
         after this file, so at equal specificity its `margin: 46px auto 0` wins
         and the gap silently stays at nothing. */
      body.chat-empty #input-area .chat-suggestions {
        margin: 0 auto 22px;
        gap: 1px;
      }

      body.chat-empty #input-area .empty-suggestion {
        padding: 11px 12px;
      }

      /* The greeting goes high and stays there: centring it in what is left
         would only wedge it against the examples. */
      body.chat-empty #chat-area {
        justify-content: flex-start;
        padding-top: 10vh;
        padding-bottom: 104px;
      }

      body.chat-empty .empty-state {
        margin: 0 auto;
        transform: none;
      }
    }

    @media (max-width: 480px) {
      .zpravy-article {
        gap: 10px;
        padding: 12px;
      }
      .zpravy-article-image {
        width: 92px;
        height: 76px;
      }
    }

    /* A software keyboard covers the stable phone canvas. JavaScript tracks
       the visual viewport and exposes only the covered height; the transcript
       keeps its geometry while the composer rises above the keyboard. */
    body.phone-composer-layout {
      height: var(--phone-app-height, 100lvh);
      min-height: var(--phone-app-height, 100lvh);
      max-height: var(--phone-app-height, 100lvh);
      overflow: hidden;
    }

    body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="chat"] #input-area,
    body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="chat"].chat-empty #input-area {
      bottom: var(--phone-keyboard-inset, 0px);
      padding-bottom: 4px;
    }

    @media (max-width: 720px) {
      body.phone-composer-layout.phone-keyboard-open .mobile-rail-toggle,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="library"] .library-toolbar-shell,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="zpravy"] .zpravy-toolbar,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"] .datasources-sidebar-controls,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"] .ds-detail-tabs {
        transform: translateY(calc(-1 * var(--phone-keyboard-inset, 0px)));
      }

      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="library"] .library-toolbar-shell,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="zpravy"] .zpravy-toolbar,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"] .datasources-sidebar-controls,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"] .ds-detail-tabs {
        position: relative;
        z-index: 60;
      }

      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="library"] .library-list {
        padding-bottom: calc(18px + var(--phone-keyboard-inset, 0px));
      }

      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="zpravy"] .zpravy-scroll {
        padding-bottom: calc(var(--main-pad) + var(--phone-keyboard-inset, 0px));
      }

      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"] .ds-list,
      body.phone-composer-layout.phone-keyboard-open[data-phone-keyboard-owner="datasources"].ds-mobile-picker-open .ds-list {
        bottom: calc(
          var(--ds-mobile-control-height)
          + var(--ds-mobile-detail-controls-height)
          + var(--phone-keyboard-inset, 0px)
          + 6px
        );
      }
    }

    /* ── History search ──────────────────────────────────────────────
       Chats and výzkumné zprávy only. A palette rather than a field in the
       rail: the rail is narrow, the results want the whole title on one line,
       and searching is a thing you do rather than a place you go. */
    .history-search-btn {
      flex: 0 0 auto;
      /* Pushed to the far edge of the rail, away from the wordmark: it is a
         tool, not part of the brand lockup. */
      margin-left: auto;
      display: grid;
      place-items: center;
      width: 30px;
      height: 30px;
      border: 0;
      border-radius: var(--r-sm);
      background: transparent;
      color: var(--muted);
      cursor: pointer;
      transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
    }

    .history-search-btn svg {
      width: 17px;
      height: 17px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
    }

    .history-search-btn:hover,
    .history-search-btn:focus-visible {
      background: var(--hover-bg);
      color: var(--ink);
    }

    .history-search-overlay {
      position: fixed;
      inset: 0;
      z-index: 1200;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      padding: 12vh 20px 20px;
      background: rgb(var(--muted-rgb) / .22);
    }

    .history-search-overlay[hidden] { display: none; }

    .history-search-panel {
      width: min(620px, 100%);
      max-height: 70vh;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      border: 1px solid var(--border);
      border-radius: var(--r-xl);
      background: var(--surface);
      box-shadow: var(--shadow-pop);
    }

    .history-search-field {
      flex: 0 0 auto;
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 14px 14px 14px 16px;
      border-bottom: 1px solid var(--border-soft);
    }

    .history-search-icon {
      flex: 0 0 auto;
      width: 17px;
      height: 17px;
      fill: none;
      stroke: var(--faint);
      stroke-width: 1.7;
      stroke-linecap: round;
    }

    #history-search-input {
      flex: 1 1 auto;
      min-width: 0;
      border: 0;
      outline: none;
      background: transparent;
      color: var(--ink);
      font: inherit;
      font-size: 15px;
    }

    #history-search-input::placeholder { color: var(--faint); }

    .history-search-close {
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      width: 26px;
      height: 26px;
      border: 0;
      border-radius: var(--r-sm);
      background: transparent;
      color: var(--faint);
      cursor: pointer;
    }

    .history-search-close svg {
      width: 15px;
      height: 15px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.7;
      stroke-linecap: round;
    }

    .history-search-close:hover { background: var(--hover-bg); color: var(--ink); }

    .history-search-results {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      padding: 6px;
    }

    .history-search-result {
      display: flex;
      align-items: center;
      gap: 11px;
      width: 100%;
      border: 0;
      border-radius: var(--r-md);
      padding: 9px 10px;
      background: transparent;
      color: var(--text);
      font: inherit;
      font-size: 13.5px;
      text-align: left;
      cursor: pointer;
    }

    .history-search-result-icon {
      flex: 0 0 auto;
      display: grid;
      place-items: center;
      width: 17px;
      height: 17px;
      color: var(--faint);
    }

    .history-search-result-icon svg {
      width: 16px;
      height: 16px;
      fill: none;
      stroke: currentColor;
      stroke-width: 1.6;
      stroke-linecap: round;
      stroke-linejoin: round;
    }

    .history-search-result-title {
      flex: 1 1 auto;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .history-search-result-when {
      flex: 0 0 auto;
      color: var(--faint);
      font-size: 12px;
    }

    /* Hover and keyboard selection are the same state: the arrow keys move the
       same highlight the pointer does, so there is only ever one place to look. */
    .history-search-result:hover,
    .history-search-result.is-active {
      background: var(--hover-bg);
      color: var(--ink);
    }

    .history-search-empty {
      padding: 22px 12px;
      color: var(--faint);
      font-size: 13.5px;
      text-align: center;
    }

    @media (max-width: 560px) {
      .history-search-overlay { padding: 8vh 12px 12px; }
      .history-search-panel { max-height: 80vh; }
    }

    /* Catalogue exports stay out of the page until asked for. The sheet uses
       the same warm surface and restrained controls as the rest of Databáze. */
    .ds-detail-download { font-family: var(--font-sans); cursor: pointer; }
    .ds-export-overlay {
      position: fixed;
      inset: 0;
      z-index: 1250;
      display: none;
      align-items: center;
      justify-content: center;
      padding: 20px;
      background: rgb(var(--muted-rgb) / .24);
      backdrop-filter: blur(5px);
    }
    .ds-export-overlay.open { display: flex; }
    .ds-export-dialog {
      width: min(560px, 100%);
      max-height: min(760px, calc(100dvh - 40px));
      display: flex;
      flex-direction: column;
      overflow: hidden;
      border: 1px solid var(--border);
      border-radius: var(--r-xl);
      background: var(--surface);
      box-shadow: var(--shadow-pop);
      color: var(--text);
      font-family: var(--font-sans);
    }
    .ds-export-head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 16px;
      padding: 18px 20px 13px;
    }
    .ds-export-head h4 {
      margin: 0;
      color: var(--ink);
      font-size: 15px;
      font-weight: 620;
      letter-spacing: -.01em;
    }
    .ds-export-head p { margin: 3px 0 0; color: var(--faint); font-size: 12px; }
    .ds-export-close {
      width: 28px;
      height: 28px;
      border: 0;
      border-radius: var(--r-sm);
      background: transparent;
      color: var(--faint);
      font: 20px/1 var(--font-sans);
      cursor: pointer;
    }
    .ds-export-close:hover { background: var(--hover-bg); color: var(--ink); }
    .ds-export-body {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      padding: 5px 20px 18px;
    }
    .ds-export-filters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
    .ds-export-field {
      min-width: 0;
      display: flex;
      flex-direction: column;
      gap: 6px;
      margin: 0;
      padding: 0;
      border: 0;
      color: var(--muted);
      font-size: 11.5px;
      font-weight: 550;
    }
    .ds-export-field > legend { padding: 0; }
    .ds-export-field > input,
    .ds-export-field > select,
    .ds-export-range input,
    .ds-export-column-tools input {
      box-sizing: border-box;
      width: 100%;
      min-height: 38px;
      border: 1px solid var(--border-input);
      border-radius: var(--r-md);
      outline: 0;
      background: var(--surface-inset);
      color: var(--ink);
      padding: 8px 10px;
      font: 13px var(--font-sans);
    }
    .ds-export-field > input:focus,
    .ds-export-field > select:focus,
    .ds-export-range input:focus,
    .ds-export-column-tools input:focus { border-color: var(--border-focus); background: var(--surface); }
    .ds-export-range { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    .ds-export-range legend { grid-column: 1 / -1; padding: 0; }
    .ds-export-range label { display: flex; align-items: center; gap: 7px; color: var(--faint); font-size: 11px; }
    .ds-export-multi {
      position: relative;
      width: 100%;
      color: var(--ink);
      font-weight: 400;
    }
    .ds-export-multi summary {
      box-sizing: border-box;
      min-height: 38px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 8px 10px;
      border: 1px solid var(--border-input);
      border-radius: var(--r-md);
      background: var(--surface-inset);
      font-size: 13px;
      cursor: pointer;
      list-style: none;
    }
    .ds-export-multi summary::-webkit-details-marker { display: none; }
    .ds-export-multi summary::after { content: '⌄'; color: var(--faint); font-size: 13px; }
    .ds-export-multi[open] summary { border-color: var(--border-focus); background: var(--surface); }
    .ds-export-multi > div {
      position: absolute;
      z-index: 3;
      top: calc(100% + 5px);
      left: 0;
      right: 0;
      max-height: 210px;
      overflow-y: auto;
      padding: 5px;
      border: 1px solid var(--border);
      border-radius: var(--r-lg);
      background: var(--surface);
      box-shadow: var(--shadow-float);
    }
    .ds-export-multi label { display: flex; align-items: center; gap: 8px; padding: 6px 7px; border-radius: var(--r-sm); color: var(--text); font-size: 12.5px; }
    .ds-export-multi label:hover { background: var(--hover-bg); }
    .ds-export-multi input { accent-color: var(--accent); }
    .ds-export-columns {
      margin-top: 15px;
      border-top: 1px solid var(--border-soft);
      border-bottom: 1px solid var(--border-soft);
    }
    .ds-export-columns summary {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      padding: 12px 2px;
      color: var(--ink);
      font-size: 13px;
      cursor: pointer;
      list-style: none;
    }
    .ds-export-columns summary::-webkit-details-marker { display: none; }
    .ds-export-columns summary span { color: var(--faint); font-size: 12px; font-weight: 400; }
    .ds-export-column-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 7px; padding: 2px 0 9px; }
    .ds-export-column-tools button,
    .ds-export-new,
    .ds-export-cancel {
      border: 1px solid var(--border);
      border-radius: var(--r-md);
      background: var(--surface);
      color: var(--muted);
      padding: 7px 10px;
      font: 12px var(--font-sans);
      cursor: pointer;
    }
    .ds-export-column-tools button:hover,
    .ds-export-new:hover,
    .ds-export-cancel:hover { background: var(--hover-bg); color: var(--ink); }
    .ds-export-column-list { max-height: 210px; overflow-y: auto; padding: 0 0 10px; }
    .ds-export-column-list label { display: flex; align-items: center; gap: 9px; padding: 6px 4px; color: var(--text); font-size: 12.5px; }
    .ds-export-column-list input { accent-color: var(--accent); }
    .ds-export-estimate { min-height: 20px; padding: 12px 2px 0; color: var(--muted); font-size: 12.5px; }
    .ds-export-estimate.error,
    .ds-export-error { color: var(--red); }
    .ds-export-footer {
      flex: 0 0 auto;
      display: flex;
      justify-content: flex-end;
      padding: 12px 20px 18px;
      border-top: 1px solid var(--border-soft);
      background: var(--surface);
    }
    .ds-export-footer[hidden] { display: none; }
    .ds-export-create {
      min-height: 38px;
      border: 0;
      border-radius: var(--r-pill);
      background: var(--accent);
      color: var(--on-accent);
      padding: 9px 17px;
      font: 600 13px var(--font-sans);
      cursor: pointer;
    }
    .ds-export-create:hover:not(:disabled) { background: var(--accent-hover); }
    .ds-export-create:disabled { opacity: .35; cursor: default; }
    .ds-export-progress { padding: 13px 2px 20px; }
    .ds-export-progress-copy { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; }
    .ds-export-progress-copy strong { color: var(--ink); font-weight: 600; }
    .ds-export-progress-copy span { color: var(--faint); }
    .ds-export-progress-track { height: 3px; margin-top: 12px; overflow: hidden; border-radius: var(--r-pill); background: var(--border-soft); }
    .ds-export-progress-track span { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width .2s ease; }
    .ds-export-complete { padding: 13px 2px 18px; }
    .ds-export-complete > strong { color: var(--ink); font-size: 14px; }
    .ds-export-complete p { margin: 7px 0; color: var(--red); font-size: 12.5px; }
    .ds-export-complete div { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
    .ds-export-complete a,
    .ds-export-history-item a { color: var(--accent); font-size: 12.5px; text-decoration: none; }
    .ds-export-complete a:hover,
    .ds-export-history-item a:hover { text-decoration: underline; }
    .ds-export-history { margin-top: 18px; padding-top: 13px; border-top: 1px solid var(--border-soft); }
    .ds-export-history h5 { margin: 0 0 8px; color: var(--muted); font-size: 11.5px; font-weight: 600; }
    .ds-export-history-item { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 7px 0; color: var(--faint); font-size: 12px; }
    .ds-export-history-item div { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }

    @media (max-width: 700px) {
      .ds-export-overlay { align-items: stretch; padding: 10px; }
      .ds-export-dialog { width: 100%; max-height: calc(100dvh - 20px); border-radius: 14px; }
      .ds-export-head { padding: 17px 17px 12px; }
      .ds-export-body { padding: 4px 17px 16px; }
      .ds-export-footer { position: sticky; bottom: 0; padding: 11px 17px 15px; }
      .ds-export-filters { grid-template-columns: 1fr; }
      .ds-export-range { grid-column: auto; }
      .ds-export-column-tools { grid-template-columns: 1fr auto; }
      .ds-export-column-tools button:last-child { display: none; }
    }

    /* Category filter in Knihovna.
       It used to be a bordered control sitting beside the search field, with a
       fixed 176px width so a long category could not shove the header sideways.
       It is the page heading now, so all of that is gone -- the look lives in
       .library-title-btn, and the width is the heading's own. These ids are
       kept only for the popup, which still needs to be wider than the default
       menu to fit a category name and its count. */
    #library-cat-dd {
      position: relative;
    }
    #library-cat-menu {
      min-width: 260px;
    }
    #library-cat-menu .ds-type-menu-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
    }
    #library-cat-menu .ds-type-menu-item small {
      opacity: .55;
      font-variant-numeric: tabular-nums;
    }

    @media (max-width: 720px) {
      /* The popup is anchored to a heading now, not to a 112px control, so it
         only needs to stay inside the viewport. */
      #library-cat-menu {
        min-width: 0;
        max-width: calc(100vw - 20px);
      }
    }

    /* ── Zprávy: brief-first daily reading page ────────────────────────────
       The brief is the document. Articles are supporting material below it,
       with their rank expressed by card size rather than by another view. */
    body[data-mode="zpravy"] .zpravy-area {
      overflow-x: hidden;
      overflow-y: auto;
      padding: 0 var(--main-pad) 0 calc(var(--rail-width) + var(--main-pad));
      scrollbar-gutter: stable;
    }

    body[data-mode="zpravy"] .zpravy-wrap {
      box-sizing: border-box;
      width: min(100%, 1140px);
      max-width: 1140px;
      height: auto;
      min-height: 0;
      margin: 0 auto;
      padding: 0 0 64px;
    }

    body[data-mode="zpravy"] .zpravy-toolbar {
      position: static !important;
      inset: auto !important;
      z-index: auto;
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: space-between;
      gap: 24px;
      width: 100%;
      max-width: none;
      margin: 0 auto;
      padding: 42px 0 18px;
      border: 0;
      border-bottom: 1px solid var(--border);
      border-radius: 0;
      background: transparent;
      box-shadow: none;
      transform: none !important;
    }

    body[data-mode="zpravy"] .zpravy-title {
      position: static;
      display: block;
      width: auto;
      height: auto;
      margin: 0;
      padding: 0;
      overflow: visible;
      clip-path: none;
      border-radius: 0;
      background: transparent;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 27px;
      font-weight: 500;
      line-height: 1.1;
      letter-spacing: -.022em;
      white-space: nowrap;
    }

    /* The title is the switch. Souhrn and Články are the same day read two
       ways, so they sit side by side at title size -- the one you are in
       carries the ink, the other waits beside it in grey. A rule under the
       active half would make this a tab bar; a title does not need one. */
    body[data-mode="zpravy"] .zpravy-view-switch {
      display: flex;
      align-items: baseline;
      gap: 20px;
      min-width: 0;
      /* Takes the free space itself, so the day and the status of a drop stay
         together at the far end instead of the day sliding to the middle for as
         long as an export is being processed. */
      margin-right: auto;
    }

    body[data-mode="zpravy"] .zpravy-view-tab {
      margin: 0;
      padding: 0;
      border: 0;
      background: transparent;
      color: var(--faint);
      font: inherit;
      letter-spacing: inherit;
      white-space: nowrap;
      cursor: pointer;
      /* Slower than the shared --dur: this is the whole of the switch's
         animation, and at 150ms the two halves simply swap colour. */
      transition: color .24s ease, opacity .24s ease;
    }

    body[data-mode="zpravy"] .zpravy-view-tab:hover:not(:disabled) { color: var(--muted); }

    body[data-mode="zpravy"] .zpravy-view-tab[aria-selected="true"] { color: var(--ink); }

    /* A day whose export never arrived has no articles to switch to. */
    body[data-mode="zpravy"] .zpravy-view-tab:disabled {
      color: var(--faint);
      opacity: .45;
      cursor: default;
    }

    body[data-mode="zpravy"] .zpravy-view-tab:focus-visible {
      border-radius: 3px;
      outline: 2px solid var(--accent);
      outline-offset: 4px;
    }

    body[data-mode="zpravy"] .news-brief-nav {
      position: static;
      display: grid;
      /* The middle track is fixed rather than 1fr because the grid itself is
         auto-width: sized to the label, the cluster grew and shrank with the
         date -- "1.1. – úterý" is 60px and "22.12. – pondělí" is 91px, so both
         chevrons slid roughly 15px every time the day changed. 112px clears the
         widest label plus its padding, and the label centres inside it.
         The phone layout has its own fixed width and is left alone. */
      grid-template-columns: 40px 112px 40px;
      align-items: center;
      gap: 2px;
      width: auto;
      min-width: 0;
      min-height: 40px;
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      background: transparent;
    }

    body[data-mode="zpravy"] .news-brief-date {
      display: flex;
      align-items: center;
      justify-content: center;
      width: auto;
      min-width: 0;
      max-width: none;
      height: 40px;
      padding: 0 8px;
      color: var(--muted);
      font-size: 13px;
      font-weight: 560;
      white-space: nowrap;
    }

    body[data-mode="zpravy"] .news-brief-nav-btn {
      width: 40px;
      height: 40px;
      border: 0;
      border-radius: 50%;
      background: transparent;
      box-shadow: none;
    }

    body[data-mode="zpravy"] .zpravy-layout {
      --zpravy-measure: 780px;
      display: flex;
      flex-direction: column;
      gap: 0;
      width: 100%;
      height: auto;
      min-height: 0;
      margin: 0;
    }

    body[data-mode="zpravy"] .zpravy-side,
    body[data-mode="zpravy"] .zpravy-main {
      position: static;
      display: block !important;
      grid-area: auto;
      width: 100%;
      height: auto;
      min-width: 0;
      min-height: 0;
      max-height: none;
      margin: 0;
      padding: 0;
      border: 0;
    }

    body[data-mode="zpravy"] .news-brief-scroll,
    body[data-mode="zpravy"] .zpravy-scroll {
      width: 100%;
      height: auto;
      min-height: 0;
      max-height: none;
      overflow: visible;
      overscroll-behavior: auto;
      padding: 0;
    }

    body[data-mode="zpravy"] .news-brief-content {
      box-sizing: border-box;
      width: min(100%, var(--zpravy-measure));
      max-width: var(--zpravy-measure);
      min-height: 0;
      margin: 0 auto;
      padding: 24px 0 56px;
    }

    body[data-mode="zpravy"] .news-brief-message {
      width: 100%;
      max-width: none;
      margin: 0;
      padding: 0;
      background: transparent;
      box-shadow: none;
    }

    body[data-mode="zpravy"] .news-brief-message .answer-text {
      max-width: none;
      padding: 0;
      color: var(--text);
      font-size: 17px;
      line-height: 1.7;
    }

    body[data-mode="zpravy"] .news-brief-message .answer-text > :first-child {
      margin-top: 0;
    }

    body[data-mode="zpravy"] .news-brief-message .answer-text h2 {
      margin-top: 35px;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 27px;
      font-weight: 500;
      letter-spacing: -.02em;
    }

    body[data-mode="zpravy"] .news-brief-empty {
      margin: 54px auto;
    }

    /* The same opening as the brief's. The rule that used to sit here was the
       seam between the two, and there is no seam now -- they are two views of
       the day, both starting under the header. */
    body[data-mode="zpravy"] .zpravy-main {
      padding-top: 24px;
    }

    /* One view at a time. */
    body[data-mode="zpravy"] .zpravy-side[hidden],
    body[data-mode="zpravy"] .zpravy-main[hidden] {
      display: none !important;
    }

    /* The view that is switched to rises into place rather than appearing cut
       in: a short fade is enough to say the page changed under a title that
       stayed put. */
    body[data-mode="zpravy"] .zpravy-side,
    body[data-mode="zpravy"] .zpravy-main {
      animation: zpravyViewIn .26s ease both;
    }

    @keyframes zpravyViewIn {
      from { opacity: 0; transform: translateY(6px); }
      to { opacity: 1; transform: none; }
    }

    body[data-mode="zpravy"] .zpravy-side-controls {
      display: none !important;
    }

    /* ...except to report on a drop. Keyed off the button's own state so there is
       one place that decides whether an upload has anything to say. */
    body[data-mode="zpravy"] .zpravy-side-controls:has(> .zpravy-upload-btn.is-busy),
    body[data-mode="zpravy"] .zpravy-side-controls:has(> .zpravy-upload-btn.is-error) {
      display: flex !important;
      /* Sized to the status it holds. It carries a full-width rule from when it
         sat above the feed, and in the header that took the whole row. */
      flex: 0 0 auto;
      width: auto;
    }

    body[data-mode="zpravy"] #zpravy-feed {
      display: block;
      width: 100%;
      max-width: none;
      margin: 0;
    }

    body[data-mode="zpravy"] .zpravy-day-group {
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      gap: 14px;
      width: 100%;
      margin: 0;
      padding: 0;
      border: 0;
    }

    body[data-mode="zpravy"] .zpravy-article {
      box-sizing: border-box;
      display: flex;
      min-width: 0;
      margin: 0;
      overflow: hidden;
      border: 1px solid var(--border);
      border-radius: 13px;
      background: var(--surface);
      color: var(--text);
      box-shadow: none;
      transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
    }

    body[data-mode="zpravy"] .zpravy-article.has-link:hover {
      border-color: var(--border-card-hover);
      box-shadow: 0 8px 24px rgba(42, 49, 33, .07);
      transform: translateY(-1px);
    }

    body[data-mode="zpravy"] .zpravy-article-info {
      display: flex;
      flex: 1 1 auto;
      flex-direction: column;
      min-width: 0;
    }

    body[data-mode="zpravy"] .zpravy-article-meta {
      order: -1;
      margin: 0 0 9px;
      padding: 0;
      border: 0;
    }

    body[data-mode="zpravy"] .zpravy-article-source {
      color: var(--accent);
      font-size: 11px;
      font-weight: 700;
      letter-spacing: .02em;
    }

    body[data-mode="zpravy"] .zpravy-article-title {
      margin: 0;
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 20px;
      font-weight: 520;
      line-height: 1.17;
      letter-spacing: -.015em;
    }

    body[data-mode="zpravy"] .zpravy-article-summary {
      display: -webkit-box;
      margin: 12px 0 0;
      overflow: hidden;
      color: var(--muted);
      font-size: 13px;
      line-height: 1.52;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 4;
    }

    body[data-mode="zpravy"] .zpravy-article-image {
      flex: 0 0 auto;
      width: auto;
      height: auto;
      overflow: hidden;
      border: 0;
      border-radius: 0;
      background: var(--surface-rail);
    }

    body[data-mode="zpravy"] .zpravy-article-image img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured {
      grid-column: span 7;
      min-height: 286px;
      flex-direction: row;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-image {
      width: 45%;
      min-height: 284px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-info {
      justify-content: center;
      padding: 28px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-title {
      font-size: 25px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured.is-image-missing {
      grid-column: 1 / -1;
      min-height: 0;
    }

    body[data-mode="zpravy"] .zpravy-article.is-featured.is-image-missing .zpravy-article-info {
      max-width: 760px;
      padding: 28px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-standard {
      grid-column: span 5;
      flex-direction: column;
    }

    body[data-mode="zpravy"] .zpravy-article.is-standard .zpravy-article-image {
      width: 100%;
      height: 154px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-standard .zpravy-article-info {
      padding: 20px 22px 22px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-standard.is-image-missing {
      grid-column: span 4;
    }

    body[data-mode="zpravy"] .zpravy-article.is-compact {
      grid-column: span 4;
      min-height: 136px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-compact .zpravy-article-info {
      justify-content: flex-start;
      padding: 19px 20px;
    }

    body[data-mode="zpravy"] .zpravy-article.is-compact .zpravy-article-image,
    body[data-mode="zpravy"] .zpravy-article.is-compact .zpravy-article-summary {
      display: none;
    }

    body[data-mode="zpravy"] .zpravy-article.is-compact .zpravy-article-title {
      font-size: 18px;
    }

    body[data-mode="zpravy"] .zpravy-empty {
      padding: 38px 20px;
      border: 1px dashed var(--border);
      border-radius: 13px;
      background: transparent;
      color: var(--faint);
      text-align: center;
    }

    @media (max-width: 900px) {
      body[data-mode="zpravy"] .zpravy-wrap {
        width: 100%;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured,
      body[data-mode="zpravy"] .zpravy-article.is-standard {
        grid-column: 1 / -1;
      }

      body[data-mode="zpravy"] .zpravy-article.is-standard {
        display: grid;
        grid-template-columns: minmax(190px, 34%) minmax(0, 1fr);
      }

      body[data-mode="zpravy"] .zpravy-article.is-standard .zpravy-article-image {
        width: 100%;
        height: 100%;
        min-height: 210px;
      }

      body[data-mode="zpravy"] .zpravy-article.is-compact {
        grid-column: span 6;
      }
    }

    @media (max-width: 720px) {
      body[data-mode="zpravy"] .zpravy-area {
        padding: 0 16px;
      }

      body[data-mode="zpravy"] .zpravy-wrap {
        /* Clears the bar pinned below it, plus the phone's home indicator. */
        padding: 0 0 calc(74px + env(safe-area-inset-bottom, 0px));
      }

      /* The day picker belongs under the thumb, not at the top edge -- the same
         place Databáze and Knihovna put their controls. The page still scrolls
         as one; only the bar leaves the flow, so the brief starts at the top of
         the screen instead of a row below it. */
      body[data-mode="zpravy"] .zpravy-toolbar {
        /* `!important` only to answer the `!important` above: the desktop rule
           un-sticks this bar so the page scrolls as one document, and without
           matching its weight the bar stays at the top edge here. */
        position: fixed !important;
        inset: auto 0 0 !important;
        z-index: 50;
        gap: 10px;
        width: 100%;
        margin: 0;
        padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
        border-radius: 0;
        border-top: 1px solid var(--border-soft);
        background: rgb(var(--surface-page-rgb) / .96);
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
      }

      /* Both names and the day share one bar across the bottom of the phone, so
         the switch is sized to what is left once the day has its width: near
         the desktop title on a large phone, a little under it on a small one. */
      body[data-mode="zpravy"] .zpravy-title {
        height: auto;
        padding: 0;
        font-size: clamp(16px, 5vw, 21px);
      }

      body[data-mode="zpravy"] .zpravy-view-switch {
        gap: clamp(10px, 3.4vw, 16px);
      }

      /* The chevrons keep their full size and the day keeps its own track, so
         the label still centres between them without moving either one: 88px
         clears the widest day of the year at this size. What is left of the bar
         is the switch's. */
      body[data-mode="zpravy"] .news-brief-nav {
        grid-template-columns: 40px 88px 40px;
        width: 168px;
      }

      body[data-mode="zpravy"] .news-brief-date {
        padding: 0 2px;
        font-size: 12px;
      }

      body[data-mode="zpravy"] .news-brief-content {
        padding: 32px 2px 44px;
      }

      body[data-mode="zpravy"] .news-brief-message .answer-text {
        font-size: 16px;
        line-height: 1.65;
      }

      body[data-mode="zpravy"] .zpravy-main {
        padding-top: 22px;
      }
      body[data-mode="zpravy"] .zpravy-day-group {
        gap: 12px;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured,
      body[data-mode="zpravy"] .zpravy-article.is-standard,
      body[data-mode="zpravy"] .zpravy-article.is-compact,
      body[data-mode="zpravy"] .zpravy-article.is-standard.is-image-missing {
        grid-column: 1 / -1;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured,
      body[data-mode="zpravy"] .zpravy-article.is-standard {
        display: flex;
        flex-direction: column;
        min-height: 0;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-image,
      body[data-mode="zpravy"] .zpravy-article.is-standard .zpravy-article-image {
        width: 100%;
        height: 180px;
        min-height: 0;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-info,
      body[data-mode="zpravy"] .zpravy-article.is-standard .zpravy-article-info,
      body[data-mode="zpravy"] .zpravy-article.is-featured.is-image-missing .zpravy-article-info {
        padding: 21px;
      }

      body[data-mode="zpravy"] .zpravy-article.is-featured .zpravy-article-title {
        font-size: 23px;
      }

      body[data-mode="zpravy"] .zpravy-article.is-compact {
        min-height: 0;
      }

      body[data-mode="zpravy"] .zpravy-article.is-compact .zpravy-article-info {
        padding: 18px 19px;
      }
    }

    @media (max-width: 410px) {
      body[data-mode="zpravy"] .zpravy-area {
        padding: 0 13px;
      }
    }

.native-input { display: grid; gap: .75rem; padding: 1rem; margin-top: .75rem; border: 1px solid var(--border-color, #ddd); border-radius: 8px; }
.native-input label { display: grid; gap: .35rem; }
.native-input input, .native-input select { padding: .5rem; max-width: 100%; color: inherit; background: transparent; border: 1px solid var(--border-color, #ddd); border-radius: 4px; }
.native-input small { opacity: .75; }
.native-input [role="alert"]:empty { display: none; }
