/* Sora carries the interface, IBM Plex Mono carries paths, hashes and checksums,
   Material Symbols carries every icon. The unicode-range values match what Google
   serves, so latin-ext is fetched only for a page that actually contains a diacritic —
   which for Croatian is most of them. */

@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/sora-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Sora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/sora-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  font-weight: 100 700;
  font-display: block;
  src: url('fonts/material-symbols-subset.woff2') format('woff2');
}

/* ============================================================
   Datarium design tokens
   ============================================================ */

:root {
  /* ── Typography families ── */
  --font-ui: "Sora", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-icon: "Material Symbols Outlined";

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* ── Type scale ── */
  --type-display: 700 34px/1.1 var(--font-ui);
  --type-title-1: 700 26px/1.15 var(--font-ui);
  --type-title-2: 700 21px/1.2 var(--font-ui);
  --type-title-3: 700 17px/1.25 var(--font-ui);

  --type-body: 400 14px/1.5 var(--font-ui);
  --type-body-strong: 600 14px/1.5 var(--font-ui);
  --type-body-mobile: 400 15px/1.5 var(--font-ui);
  --type-small: 400 13px/1.45 var(--font-ui);
  --type-caption: 400 12px/1.4 var(--font-ui);

  --type-overline: 700 11.5px/1.2 var(--font-ui);
  --overline-tracking: 0.06em;
  --eyebrow-tracking: 0.1em;

  --type-mono: 400 12.5px/1.55 var(--font-mono);
  --type-mono-small: 400 11.5px/1.5 var(--font-mono);

  --tracking-tight: -0.01em;
  --tracking-display: -0.02em;
  --numeric-table: tabular-nums;

  /* ── Brand, taken from the logo mark ── */
  --blue-700: #0F1A2E;
  --blue-600: #1B2A47;
  --blue-500: #2E5692;
  --blue-400: #0071BC;
  --blue-300: #4FA3E3;
  --blue-100: #E8F1F9;
  --blue-050: #F4F9FD;

  --orange-600: #B44A14;
  --orange-500: #F26A2E;
  --orange-400: #F59353;
  --orange-300: #FAAF3B;
  --orange-200: #F8D9B8;
  --orange-100: #FFF7EE;
  --orange-050: #FFF0E6;

  /* ── Neutrals ── */
  --ink-900: #171B26;
  --ink-700: #4B5260;
  --ink-500: #7C8494;
  --ink-400: #9AA1AE;
  --ink-300: #C9CDD6;
  --line-200: #E4E7EC;
  --grey-100: #F2F4F7;
  --grey-050: #F7F8FA;
  --white: #FFFFFF;

  /* ── Status ── */
  --ok-fg: #1E7A46;
  --ok-bg: #E6F6EC;
  --ok-500: #5BD08F;
  --warn-fg: #8A6100;
  --warn-bg: #FFF7E0;
  --danger-fg: #B3261E;
  --danger-bg: #FDECEA;
  --danger-500: #E4685D;
  --info-fg: #2E5692;
  --info-bg: #E8F1F9;

  /* ── Semantic aliases: light theme (default) ── */
  --surface-app: var(--grey-050);
  --surface-card: var(--white);
  --surface-sunken: var(--grey-100);
  --surface-nav: linear-gradient(180deg, #1B2A47, #0F1A2E);
  --surface-launcher: var(--white);
  --surface-selected: var(--blue-100);
  --surface-overlay: rgba(23, 27, 38, 0.45);

  --text-primary: var(--ink-900);
  --text-secondary: var(--ink-700);
  --text-muted: var(--ink-500);
  --text-placeholder: var(--ink-400);
  --text-on-nav: #C9D3E6;
  --text-on-nav-strong: var(--white);
  --text-on-nav-muted: #8FA0BF;
  --text-link: var(--blue-400);
  --text-link-hover: var(--blue-500);

  --border-subtle: rgba(0, 0, 0, 0.06);
  --border-default: rgba(0, 0, 0, 0.1);
  --border-strong: rgba(0, 0, 0, 0.14);
  --border-focus: var(--blue-400);
  /* The focus ring on the nav surface: at least 3:1 against both ends of --surface-nav. */
  --border-focus-nav: var(--blue-300);

  --action-primary-bg: var(--orange-500);
  --action-primary-fg: var(--white);
  --action-secondary-bg: var(--blue-100);
  --action-secondary-fg: var(--blue-400);
  --action-quiet-fg: var(--ink-700);
  --action-danger-bg: var(--danger-bg);
  --action-danger-fg: var(--danger-fg);

  --accent-nav: var(--blue-400);
  --accent-upload: var(--orange-500);
  --accent-nav-marker: var(--orange-300);

  /* ── Spacing scale ── */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 10px;
  --space-6: 12px;
  --space-7: 14px;
  --space-8: 16px;
  --space-9: 20px;
  --space-10: 24px;
  --space-11: 28px;
  --space-12: 32px;
  --space-14: 40px;
  --space-16: 48px;

  /* ── Frame geometry ── */
  --nav-width: 224px;
  --nav-width-collapsed: 64px;
  --launcher-width: 322px;
  --launcher-width-collapsed: 62px;
  --topbar-height: 62px;
  --detail-panel-width: 300px;
  --bottom-nav-height: 82px;
  --page-gutter: 24px;
  --page-gutter-mobile: 16px;

  /* ── Controls ── */
  --control-height-sm: 34px;
  --control-height: 42px;
  --control-height-lg: 46px;
  --control-height-mobile: 50px;
  --row-height: 60px;
  --row-height-compact: 56px;
  --touch-target-min: 44px;

  /* ── Radii ── */
  --radius-xs: 6px;
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 12px;
  --radius-xl: 14px;
  --radius-2xl: 22px;
  --radius-pill: 999px;
  --radius-phone: 36px;

  /* ── Elevation ── */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-raised: 0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-popover: 0 10px 24px rgba(0, 0, 0, 0.12);
  --shadow-dialog: 0 24px 60px rgba(0, 0, 0, 0.26);
  --shadow-sheet: 0 -10px 30px rgba(0, 0, 0, 0.08);
  --shadow-fab: 0 6px 16px rgba(242, 106, 46, 0.32);
  --shadow-fab-blue: 0 6px 16px rgba(0, 113, 188, 0.32);

  --selected-marker: inset 3px 0 0 var(--accent-nav);
  --tab-marker: inset 0 -3px 0 var(--accent-nav);

  /* ── Motion ── */
  --duration-fast: 120ms;
  --duration-base: 180ms;
  --duration-slow: 260ms;
  --ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);

  --hover-tint: rgba(0, 0, 0, 0.03);
  --press-tint: rgba(0, 0, 0, 0.06);

  /* ── Breakpoints (for reference; media queries cannot read custom properties) ── */
  --breakpoint-sm: 480px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;

  /* Avatar tones: a name keeps one tone everywhere it appears. Drawn from the logo's blues,
     its orange and the neutral and status palettes, never from a new hue. */
  --avatar-1-bg: var(--blue-400);   --avatar-1-fg: var(--white);
  --avatar-2-bg: #FDEBD9;           --avatar-2-fg: #9A4A16;
  --avatar-3-bg: var(--blue-100);   --avatar-3-fg: var(--blue-500);
  --avatar-4-bg: #EEF0F4;           --avatar-4-fg: var(--ink-700);
  --avatar-5-bg: var(--ok-bg);      --avatar-5-fg: var(--ok-fg);
  --avatar-6-bg: var(--orange-050); --avatar-6-fg: var(--orange-600);
  --avatar-7-bg: var(--blue-500);   --avatar-7-fg: var(--white);
  --avatar-8-bg: var(--warn-bg);    --avatar-8-fg: var(--warn-fg);

  /* Tints on the navy bar: a hover, an active item, and a hairline. */
  --nav-tint-1: rgba(255, 255, 255, 0.08);
  --nav-tint-2: rgba(255, 255, 255, 0.14);
  --nav-tint-border: rgba(255, 255, 255, 0.16);
}

/* END TOKENS */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--surface-app);
  color: var(--text-primary);
  font: var(--type-body);
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

a { color: var(--text-link); text-decoration: none; }
a:hover { color: var(--text-link-hover); text-decoration: underline; }

/* An anchor drawn as a control keeps its label plain: the underline above says "text" where
   the shape says "button", and on a control whose whole label is a glyph it lands under the
   glyph. The hover selectors are what carry that, since `a:hover` outweighs a class on its
   own and applies to every anchor these classes are written on. */
.ds-btn,
.ds-pagination__arrow,
.surface__brand,
.ds-btn:hover,
.ds-pagination__arrow:hover,
.surface__brand:hover { text-decoration: none; }

button, input, select, textarea { font: inherit; color: inherit; }

::selection { background: var(--blue-100); }

:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

/* Material Symbols glyph helper: <span class="ds-icon">upload</span> */
.ds-icon {
  font-family: var(--font-icon);
  font-weight: 400;
  font-style: normal;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  direction: ltr;
  -webkit-font-smoothing: antialiased;
  font-variation-settings: "opsz" 24, "wght" 400, "FILL" 0;
  user-select: none;
}
.ds-icon[data-filled="true"] { font-variation-settings: "FILL" 1; }

/* Any number or date outside a table's numeric column. */
.ds-num { font-variant-numeric: var(--numeric-table); }

/* ============================================================
   Typography helpers
   ============================================================ */

/* A name a reader needs where the layout has no room to draw it: a column of glyphs, a bar
   collapsed to its controls. Clipped to a 1px box it leaves the layout without leaving the
   document, so it keeps its place in the accessibility tree — display: none would take it out
   of both. */
.ds-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* A table column header or a section eyebrow above a block. Table headers use
   --overline-tracking; a standalone eyebrow uses --eyebrow-tracking. */
.eyebrow {
  font: var(--type-overline);
  letter-spacing: var(--overline-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ============================================================
   Layout archetypes
   ============================================================ */

/* A surface with exactly one task and no way out but finishing it: one card on
   a full-bleed gradient field, with the colophon line beneath it.
   The rows are packed and centred as one group rather than left to stretch, which
   would spread the card and the line to the quarter points of the field. `safe`
   keeps a card taller than the viewport flush with the top, where the whole of it
   can still be scrolled to. */
.focused {
  display: grid;
  place-items: center;
  align-content: safe center;
  gap: var(--space-12);
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--page-gutter-mobile);
  background: var(--surface-nav);
}

.focused__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-8);
  width: 100%;
  /* A grid item's automatic minimum size is its min-content width, which on a narrow
     screen is wider than the field's gutter leaves for it. */
  min-width: 0;
  max-width: 380px;
  padding: var(--space-14) var(--space-10);   /* 40px 24px */
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-dialog);
  text-align: center;
}

/* The card's surface is the light ground the mark is drawn for, so the mark stands on it with
   no tile of its own. The heading block is centred whichever way the card aligns its body, and a
   box of a fixed size answers to align-self rather than to text-align. */
.focused__mark { display: block; align-self: center; }
.focused__mark .ds-mark { height: 64px; }

.focused__title {
  margin: 0;
  font: var(--type-title-2);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  text-align: center;
}

.focused__text { margin: 0; font: var(--type-body); color: var(--text-muted); text-align: center; }

/* A machine value inside the archetype's running text. A secret is transcribed character by
   character and the body face makes 1 and l, 0 and O the same shape, so the pair resolves to
   the mono face and its ink by weight rather than by the order the two rules are written in. */
.focused__text.ds-mono { font: var(--type-mono); color: var(--text-secondary); }

/* A form reads badly centred even when the card holding it is centred, so the
   form block sets its own contents left while the heading above it stays
   centred with the card. */
.focused__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-9);
  width: 100%;
  text-align: left;
}

/* A card carrying a form is wider than one carrying only a message, and everything
   in it reads from the left: a field, a label or a notice beside a glyph is unreadable
   centred. The heading block above it keeps its own centring. */
.focused__card:has(.focused__form) { max-width: 420px; align-items: stretch; text-align: left; }

/* A surface with no navigation to offer. The shell is what gutters and measures
   content in the framed archetype; without it the surface does both itself, and
   1120px is the measure a framed list reads at. */
.surface { min-height: 100dvh; background: var(--surface-app); }

.surface__bar {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  height: var(--topbar-height);
  padding-inline: var(--page-gutter);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--surface-card);
}

/* The bar names the product at one end and the person at the other. */
.surface__brand {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  font: var(--type-title-3);
  color: var(--text-primary);
}

/* The wordmark names the product rather than a destination, so it keeps its ink under the
   pointer where the anchor rules would give it the link colour. */
.surface__brand:hover { color: var(--text-primary); }

.surface__brand img { display: block; height: 28px; width: auto; }

/* The product name carries the weight; the surface it names sits back from it. */
.surface__brand span span { font-weight: var(--weight-regular); color: var(--text-muted); }

.surface__user {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin-inline-start: auto;
  font: var(--type-small);
  color: var(--text-muted);
}

/* The name carries the hidden geometry, and the bar draws it only where there is room for it
   beside the two controls. Narrower than this the strip is glyphs alone, and the name stays in
   the accessibility tree: it is what tells a reader whose session the surface shows. */
@media (min-width: 768px) {
  .surface__user-name.ds-visually-hidden {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }
}

.surface__content {
  max-width: 1120px;
  margin: 0 auto;
  padding: var(--space-10) var(--page-gutter);
}

/* A list with a machine value in it needs more room than the reading measure: the
   column tiers are sized against the table's own width, and at 1120px the table can
   never reach the width at which the widest columns earn their place. */
.surface__content[data-measure="wide"] { max-width: 1280px; }

/* The bar cannot hold the name and the action labels at phone width, so the strip
   collapses to its glyphs and each control keeps its name on its aria-label. */
@media (max-width: 767px) {
  .surface__bar { padding-inline: var(--page-gutter-mobile); gap: var(--space-4); }
  .surface__content { padding: var(--space-8) var(--page-gutter-mobile); }
  .surface__user { gap: var(--space-2); }

  .surface__user-label { display: none; }

  /* Stripped of their labels the two controls are bare glyphs, and a glyph at this width is
     answered by a finger. */
  .surface__user .ds-btn {
    min-width: var(--touch-target-min);
    min-height: var(--touch-target-min);
  }
}

/* ============================================================
   The page contract
   ============================================================ */

.page {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);          /* 24px */
  min-width: 0;
}

/* Title, a factual countable subtitle, and at most one primary action. */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-9);           /* 20px */
  min-width: 0;
}

.page-head__text { flex: 1; min-width: 0; }

.page-head h1 {
  margin: 0;
  font: var(--type-title-1);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
}

.page-head p {
  margin: var(--space-2) 0 0;
  font: var(--type-small);
  color: var(--text-muted);
}

/* The search field and the compact controls that stayed structured. */
.page-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-6);           /* 12px */
  min-width: 0;
}

.page-toolbar__search { flex: 1; min-width: 260px; }

/* A filter row's controls share the row and wrap onto the next. 300px is the smallest basis
   that never leaves one control alone on a line at any width this shell reaches, and a lone
   control grows to the whole line. A control may still shrink below the basis: a phone's row
   is narrower than 300px, and a floor there would push the control past the card. A control
   that names itself the toolbar's search is excluded, so this rule never outranks that
   class. */
.page-toolbar > .ds-field:not(.page-toolbar__search),
.page-toolbar > .ds-select:not(.page-toolbar__search) { flex: 1 1 300px; min-width: 0; }

/* The search field keeps its own sizing inside a toolbar, at the specificity the filter rule
   beside it carries. Its 260px floor is safe where the filter controls' would not be, because
   the narrow-width block below lifts it to the whole row before the row gets shorter than the
   floor — which is why that block repeats this selector rather than the bare class. */
.page-toolbar > .page-toolbar__search { flex: 1; min-width: 260px; }

/* A reading surface rather than a working one: an invoice, a claim, a single
   record with no list beside it. A narrowed page centres itself: nothing anchors
   its left edge the way a navigation rail anchors a framed one. */
.page--reading { max-width: 880px; margin-inline: auto; }

/* A page whose card carries a form narrows to a form's measure; the reading measure is
   for prose and records, and a PIN field 830px wide is neither. */
.page--form { max-width: 520px; margin-inline: auto; }

@media (max-width: 767px) {
  .page { gap: var(--space-8); }            /* 16px */
  .page-head { gap: var(--space-6); }
  .page-toolbar__search,
  .page-toolbar > .page-toolbar__search { min-width: 100%; }
}

/* ============================================================
   Components
   ============================================================ */

/* ── Mark: the Datarium logo mark ── */

/* The mark file is cropped to its artwork, so the image box is the mark's own edge. The box a
   page sets the mark in gives it a height, and the width follows the mark's proportions; 24px
   is the smallest height at which its parts still read apart. The mark is drawn for a light
   ground: on a dark one it keeps a light tile around it, and it is never redrawn to fit. */
.ds-mark { display: block; width: auto; height: 24px; }

/* ── Actions row: the controls that close a card or a page block ── */

/* Actions closing a card sit at their own width rather than stretching to the card's. A row
   that mixes control sizes — a 46px field beside a 42px button — aligns on centre rather than
   stretching either to the other's height. */
.ds-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-6); }

/* ── Status badge: record state, never decoration ── */

.ds-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font: 600 12px/1.3 var(--font-ui);
  white-space: nowrap;
}

/* A badge in a table cell competes for the track with everything else in it. The label ends
   inside the pill, which it can only do while the pill itself is no wider than the cell: an
   inline-flex box lays out at max-content, so the ellipsis engages only because .ds-table td
   caps the badge at the track's width. */
.ds-badge__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ds-badge__label:empty { display: none; }

.ds-badge__icon { font-size: 15px; }

.ds-badge[data-tone="ok"]      { background: var(--ok-bg);     color: var(--ok-fg); }
.ds-badge[data-tone="warn"]    { background: var(--warn-bg);   color: var(--warn-fg); }
.ds-badge[data-tone="danger"]  { background: var(--danger-bg); color: var(--danger-fg); }
.ds-badge[data-tone="info"]    { background: var(--info-bg);   color: var(--info-fg); }
.ds-badge[data-tone="neutral"] { background: var(--grey-100);  color: var(--text-secondary); }

/* ── Button ── */

.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  white-space: nowrap;
  cursor: pointer;
  transition:
    filter var(--duration-fast) var(--ease-standard),
    background-color var(--duration-fast) var(--ease-standard),
    opacity var(--duration-fast);
}

.ds-btn[disabled] { cursor: not-allowed; opacity: 0.45; }

/* Sizes */
.ds-btn[data-size="sm"] { height: var(--control-height-sm);     padding: 0 12px; font: var(--type-small); }
.ds-btn[data-size="md"] { height: var(--control-height);        padding: 0 18px; font: var(--type-body-strong); }
.ds-btn[data-size="lg"] { height: var(--control-height-mobile); padding: 0 22px; font: 600 15.5px/1.4 var(--font-ui); }

/* Variants */
.ds-btn[data-variant="primary"]   { background: var(--action-primary-bg);   color: var(--action-primary-fg); box-shadow: var(--shadow-card); }
.ds-btn[data-variant="secondary"] { background: var(--action-secondary-bg); color: var(--action-secondary-fg); }
.ds-btn[data-variant="outline"]   { background: var(--surface-card);        color: var(--action-quiet-fg); border-color: var(--border-default); }
.ds-btn[data-variant="quiet"]     { background: transparent;                color: var(--action-quiet-fg); }
.ds-btn[data-variant="danger"]    { background: var(--action-danger-bg);    color: var(--action-danger-fg); }

/* Pressing darkens the surface without moving it. */
.ds-btn:not([disabled]):hover  { filter: brightness(0.96); }
.ds-btn:not([disabled]):active { filter: brightness(0.92); }

.ds-btn[data-variant="outline"]:not([disabled]):hover,
.ds-btn[data-variant="quiet"]:not([disabled]):hover  { filter: none; background-color: var(--hover-tint); }
.ds-btn[data-variant="outline"]:not([disabled]):active,
.ds-btn[data-variant="quiet"]:not([disabled]):active { filter: none; background-color: var(--press-tint); }

.ds-btn[data-full-width="true"] { display: flex; width: 100%; }

/* ── Card: the base surface. Everything that is not the page background sits on one. ── */

.ds-card {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 0;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.ds-card[data-radius="lg"] { border-radius: var(--radius-lg); }
.ds-card[data-radius="xl"] { border-radius: var(--radius-xl); }

/* A sunken card groups without floating. */
.ds-card[data-inset="true"] { background: var(--surface-sunken); box-shadow: none; }

.ds-card__header {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-7) var(--space-9);   /* 14px 20px */
  border-bottom: 1px solid var(--border-subtle);
}

.ds-card__title    { font: var(--type-title-3); }
.ds-card__subtitle { margin-top: 2px; font: var(--type-caption); color: var(--text-muted); }
.ds-card__icon     { font-size: 20px; color: var(--accent-nav); }

.ds-card__body { display: flex; flex-direction: column; gap: var(--space-7); min-width: 0; }

.ds-card[data-padding="sm"]   .ds-card__body { padding: var(--space-7); }   /* 14px */
.ds-card[data-padding="md"]   .ds-card__body { padding: var(--space-9); }   /* 20px */
.ds-card[data-padding="lg"]   .ds-card__body { padding: var(--space-10); }  /* 24px */

/* An unpadded card is holding a table, and the paging control is that card's
   last row — a gap would detach it from the rows it pages. */
.ds-card[data-padding="none"] .ds-card__body { padding: 0; gap: 0; }

/* ── Empty state ── */

.ds-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  padding: var(--space-12) var(--space-9);   /* 32px 20px */
  border-radius: var(--radius-lg);
  text-align: center;
}

.ds-empty__glyph       { font-size: 30px; color: var(--text-placeholder); }
.ds-empty__title       { margin: 0; font: var(--type-title-3); color: var(--text-primary); }
.ds-empty__description { margin: 0; max-width: 420px; font: var(--type-small); color: var(--text-muted); }

/* A drop target. */
.ds-empty[data-dashed="true"] { border: 2px dashed var(--border-default); }
.ds-empty[data-dashed="true"][data-tone="upload"] { border-color: var(--orange-200); background: var(--orange-100); }

/* ── Text field: the label sits above the box, never inside it ── */

.ds-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);          /* 6px */
  width: 100%;
  min-width: 0;
}

.ds-field__label {
  font: 600 12.5px/1.3 var(--font-ui);
  color: var(--text-secondary);
}

.ds-field__control {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-width: 0;
  padding: 0 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  color: var(--text-primary);
}

.ds-field[data-size="sm"] .ds-field__control { height: var(--control-height-sm);     font: 500 15px/1.4 var(--font-ui); }
.ds-field[data-size="md"] .ds-field__control { height: var(--control-height-lg);     font: 500 15px/1.4 var(--font-ui); }
.ds-field[data-size="lg"] .ds-field__control { height: var(--control-height-mobile); font: 500 16px/1.4 var(--font-ui); }

.ds-field__control:focus-within { border: 1.5px solid var(--border-focus); }

/* The input suppresses its own outline, so the ring is drawn on the control around it. It
   answers that input alone: a control may also hold a button — revealing a password, copying a
   value — which takes a ring of its own, and two rings inside one another read as a smear
   rather than as a position. The ring sits outside the border, so an error-marked control shows
   its danger border and the ring together and focus stays visible on the one field that has to
   be corrected. */
.ds-field__control:has(> .ds-field__input:focus-visible) {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

/* An error outranks focus: the field stays marked while it is corrected. */
.ds-field[data-error="true"] .ds-field__control,
.ds-field[data-error="true"] .ds-field__control:focus-within {
  border: 1.5px solid var(--danger-fg);
}

.ds-field[data-disabled="true"] .ds-field__control { opacity: 0.55; cursor: not-allowed; }

.ds-field__icon { font-size: 20px; color: var(--text-muted); }

.ds-field__input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  color: inherit;
}

.ds-field__input::placeholder { color: var(--text-placeholder); }

.ds-field__error { font: var(--type-caption); color: var(--danger-fg); }
.ds-field__hint  { font: var(--type-caption); color: var(--text-placeholder); }

/* An action inside a control — revealing a password, copying a value — is drawn as a
   glyph but answers a finger, so it keeps the minimum target whatever size it looks. */
.ds-field__action,
.ds-mono-value__copy { min-width: var(--touch-target-min); min-height: var(--touch-target-min); }

/* ── Machine values ── */

/* A path, hash or checksum inside running text or a table cell. */
.ds-mono { font: var(--type-mono); color: var(--text-secondary); }

/* Hashes have no word boundaries, so wrapping has to break inside the token. */
.ds-mono[data-wrap="true"] { word-break: break-all; }

/* A labelled machine value standing on its own: a recovery key, a fingerprint. */
.ds-mono-value {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

/* The value spans its container rather than shrink-wrapping to its text, and reads left
   whatever that container centres: a key is copied or transcribed character by character. */
.ds-mono-value { align-self: stretch; text-align: left; }

.ds-mono-value__label {
  font: var(--type-overline);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ds-mono-value__box {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-width: 0;
  padding: 10px 11px;
  background: var(--grey-050);
  border-radius: var(--radius-sm);
}

.ds-mono-value__text {
  flex: 1;
  min-width: 0;
  font: var(--type-mono);
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ds-mono-value__text[data-size="sm"] { font: var(--type-mono-small); }

.ds-mono-value__text[data-wrap="true"] {
  overflow: visible;
  white-space: normal;
  word-break: break-all;
}

.ds-mono-value__copy {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-link);
  font: 600 13px/1.3 var(--font-ui);
  cursor: pointer;
}

.ds-mono-value__copy .ds-icon { font-size: 19px; }

/* ── Inline notice: a rule, a consequence or a warning, inside the form or panel it applies to ── */

.ds-notice {
  display: flex;
  gap: var(--space-5);
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-lg);
}

/* A notice pins its glyph to the left, so its body reads left whatever its container
   centres, and it spans that container rather than shrink-wrapping to its text. */
.ds-notice { align-self: stretch; text-align: left; }

.ds-notice__glyph { flex: none; font-size: 20px; }
.ds-notice__body  { min-width: 0; font: var(--type-small); line-height: 1.55; }
.ds-notice__title { display: block; margin-bottom: 4px; font: 600 13px/1.4 var(--font-ui); }

/* The tone carries meaning: info explains, warn and danger stop the user. */
.ds-notice[data-tone="info"]   { background: var(--grey-050);   border-color: var(--border-subtle); color: var(--text-secondary); }
.ds-notice[data-tone="warn"]   { background: var(--orange-100); border-color: var(--orange-200);    color: var(--orange-600); }
.ds-notice[data-tone="ok"]     { background: var(--ok-bg);      border-color: var(--ok-500);        color: var(--ok-fg); }
.ds-notice[data-tone="danger"] { background: var(--danger-bg);  border-color: var(--danger-500);    color: var(--danger-fg); }

/* display: flex outranks the user agent's [hidden] rule, so a notice the page hides
   would otherwise stay visible. */
.ds-notice[hidden] { display: none; }

/* ── Pagination: one paging control for every list, and the card's last row ── */

.ds-pagination {
  /* The size an arrow is drawn at. Its target is --touch-target-min whatever this says. */
  --arrow-size: 32px;
  display: flex;
  align-items: center;
  gap: var(--space-7);
  min-width: 0;
  padding: 11px var(--space-9);
  font: var(--type-small);
  color: var(--text-muted);
}

.ds-pagination__spacer { flex: 1; }

.ds-pagination__range { white-space: nowrap; }

/* The arrows are spaced one target apart: two targets that overlap hand a finger to whichever
   arrow the markup writes last, so the gap is exactly what the answered area needs beyond the
   drawn one. */
.ds-pagination__arrows { display: flex; gap: calc(var(--touch-target-min) - var(--arrow-size)); }

.ds-pagination__arrow {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--arrow-size);
  height: var(--arrow-size);
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--grey-100);
  color: var(--text-primary);
  cursor: pointer;
}

/* An arrow is drawn at the size the paging strip is proportioned for and answered at the size a
   finger needs: the overlay carries no paint, so it enlarges the target without enlarging the
   control. */
.ds-pagination__arrow::after {
  content: "";
  position: absolute;
  inset: calc((var(--arrow-size) - var(--touch-target-min)) / 2);
}

.ds-pagination__arrow .ds-icon { font-size: 19px; }

.ds-pagination__arrow[disabled] { color: var(--ink-300); cursor: default; }

/* The arrow darkens its own ground under the pointer and keeps its ink, where the anchor
   rules would give it the link colour. */
.ds-pagination__arrow:not([disabled]):hover { filter: brightness(0.96); color: var(--text-primary); }

/* On a phone the control reduces to previous, range and next, and its targets grow to
   touch size: there it sits above the bottom navigation rather than inside the scrolling
   list. No script runs on these surfaces, so the viewport selects this form. */
@media (max-width: 767px) {
  .ds-pagination {
    justify-content: center;
    gap: var(--space-5);
    padding: var(--space-3) var(--space-7);
    font: var(--type-caption);
  }

  .ds-pagination__label,
  .ds-pagination__spacer,
  .ds-pagination__edge { display: none; }

  .ds-pagination__range { padding: 0 var(--space-2); }

  /* Here the arrow is drawn at the size it is answered at, so the overlay collapses onto it and
     the arrows need no room between them to keep their areas apart. */
  .ds-pagination { --arrow-size: var(--touch-target-min); }
}

/* ── Select field ── */

.ds-select { display: flex; flex-direction: column; gap: var(--space-3); width: 100%; min-width: 0; }

.ds-select__label { font: 600 12.5px/1.3 var(--font-ui); color: var(--text-secondary); }

/* The control is a native <select>, which draws its own arrow inside its right edge. The
   padding there is the gap that keeps the value clear of that arrow, not room for a second
   one drawn over it. */
.ds-select__control {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 0;
  height: var(--control-height-lg);
  padding: 0 24px 0 12px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--surface-card);
  color: var(--text-primary);
  font: var(--type-body-strong);
  cursor: pointer;
}

.ds-select__control[data-empty="true"] { font: var(--type-body); color: var(--text-placeholder); }

/* ── List: a table inside an unpadded card, with pagination as that card's last row ──
   These surfaces carry a semantic table and have no script to measure tracks with, so
   the browser owns column sizing. A fixed layout is what makes a cell truncate instead
   of widening its column: a list never scrolls sideways, it drops columns and then
   collapses into record cards. */

.ds-table {
  width: 100%;
  min-width: 0;
  table-layout: fixed;
  border-collapse: collapse;
  font: var(--type-body);
}

.ds-table th {
  padding-block: 11px;
  border-bottom: 1px solid var(--border-subtle);
  font: var(--type-overline);
  letter-spacing: var(--overline-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: left;
}

.ds-table tbody tr {
  height: var(--row-height);
  border-bottom: 1px solid var(--border-subtle);
}

.ds-table td { padding-block: 0; vertical-align: middle; }

/* A cell shows what fits and ends in an ellipsis; the column keeps its width. */
.ds-table th,
.ds-table td {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The gutter at a row's ends belongs to the cells sitting there, and every other
   cell carries the gap to the next column on its right. These stay at one class of
   specificity so a narrower layout can repad a cell. */
.ds-table :where(th, td) { padding-inline-end: var(--space-7); }
.ds-table :where(th:first-child, td:first-child) { padding-inline-start: var(--space-9); }
.ds-table :where(th:last-child, td:last-child) { padding-inline-end: var(--space-9); }

/* Under a fixed layout every column is equal unless it says otherwise. A column carrying
   a count, a date or a state declares what it needs. */
.ds-table th[data-width="xs"] { width: 9%; }
.ds-table th[data-width="sm"] { width: 13%; }
.ds-table th[data-width="md"] { width: 18%; }

/* A declared width is a share of the table, so a column left unsized takes only the residue —
   and that residue falls as the widest tier admits more columns, which is the opposite of what
   the column a row is identified by needs. Identity therefore declares a share of its own,
   large enough that the shares sum past the table where every column shows. The browser then
   scales them down together, which keeps their proportions and keeps identity the widest
   column at every width. */
.ds-table th[data-width="identity"] { width: 60%; }

.ds-table th[data-align="right"],
.ds-table td[data-align="right"] { text-align: right; }

/* A cell holding more than one thing — an icon and its label, a badge and a
   count — spaces them rather than running them together. */
.ds-table td > * + * { margin-inline-start: var(--space-5); }

/* A badge lays out at max-content, which is wider than most tracks, so in a cell it is capped
   at the track: the label inside it ellipsises and the pill keeps its shape, rather than the
   cell's overflow cutting the pill and its background mid-word. A badge that follows something
   carries the gap above onto its own line when the cell wraps, so its cap leaves room for it. */
.ds-table td .ds-badge { max-width: 100%; }
.ds-table td > * + .ds-badge { max-width: calc(100% - var(--space-5)); }

/* Actions end their row and sit tight against each other. */
.ds-table td[data-actions="true"] { text-align: right; }
.ds-table td[data-actions="true"] > * + * { margin-inline-start: var(--space-1); }

/* The only control in a row answers a finger, not a cursor, whatever size it is drawn. */
.ds-table td[data-actions="true"] .ds-btn { min-width: var(--touch-target-min); min-height: var(--touch-target-min); }

/* A cell that wraps carries either a machine value or ordinary prose, and each breaks on its
   own terms: a hash has no break opportunity of its own and breaks wherever it must, while a
   sentence keeps breaking at its words. Wrapping rather than ellipsising is what keeps a hash
   readable and selectable where there is no control to copy it with. The row grows to fit,
   since --row-height is a row's minimum rather than a cap. */
.ds-table td[data-wrap="true"] { white-space: normal; overflow-wrap: anywhere; }
.ds-table td[data-muted="true"] { color: var(--text-muted); }

/* ============================================================
   Column priority and the record-card collapse
   ============================================================ */

/* The design system sizes a column against the table's own width, not the window's:
   the same list is a full-width page on one screen and a column inside a dialog on
   another, and only its own width says whether a cell has room to be readable. */
.ds-table-host { container-type: inline-size; }

@container (max-width: 1099px) {
  .ds-table [data-tier="xl"] { display: none; }
}

@container (max-width: 849px) {
  .ds-table [data-tier="lg"] { display: none; }
}

/* Below 768px a table is a stack of record cards carrying the same data. Each cell
   names itself from the header it lost. */
@media (max-width: 767px) {
  .ds-table, .ds-table tbody, .ds-table tr, .ds-table td { display: block; width: 100%; }
  .ds-table thead { display: none; }

  .ds-table tr {
    margin-bottom: var(--space-6);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    background: var(--surface-card);
  }

  .ds-table td {
    display: flex;
    gap: var(--space-5);
    justify-content: space-between;
    align-items: baseline;
    padding: var(--space-4) var(--space-7);
    border: 0;
    text-align: right;
  }

  .ds-table td::before {
    content: attr(data-label);
    flex: none;
    font: var(--type-overline);
    letter-spacing: var(--overline-tracking);
    text-transform: uppercase;
    color: var(--text-muted);
    text-align: left;
  }

  .ds-table td[data-label=""]::before { content: none; }

  /* Column tiers exist because a table has limited horizontal room. A stack of cards has
     vertical room instead, so every column the table drops is back in the card. */
  .ds-table td[data-tier] { display: flex; }

  /* A card is as tall as the data it carries, and a value in it is read whole rather than
     truncated to a column's width. A checksum or an underscore-joined name carries no break
     opportunity of its own, so one is allowed anywhere: without it a single token pushes the
     card past the screen and the document scrolls sideways. */
  .ds-table tbody tr { height: auto; }

  .ds-table td {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
  }
}

/* ============================================================
   Surface-local components
   ============================================================ */

/* Account setup runs as four server-rendered steps; the rail states which one the person
   is on and which are behind them. The rail is drawn between circles rather than under
   them so a completed segment reads as progress, not as an underline. */
.ds-steps { display: flex; gap: var(--space-2); width: 100%; }
.ds-steps__step { flex: 1; min-width: 0; text-align: center; }

.ds-steps__dot {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  margin: 0 auto var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--text-muted);
  font: var(--type-caption);
  font-weight: var(--weight-semibold);
}

.ds-steps__step[data-state="active"] .ds-steps__dot { background: var(--accent-nav); color: var(--white); }

/* A step behind the reader carries a mark in place of its number, so which steps are done is
   readable without reading the tone: the number only says where the step sits in the sequence,
   which the rail already shows by position. */
.ds-steps__step[data-state="done"] .ds-steps__dot { background: var(--ok-bg); color: var(--ok-fg); }
.ds-steps__dot .ds-icon { font-size: 18px; }
.ds-steps__label { font: var(--type-caption); color: var(--text-muted); }
.ds-steps__step[data-state="active"] .ds-steps__label { color: var(--text-primary); font-weight: var(--weight-semibold); }

/* The meter restates the rule in the hint slot; it never replaces the rule with a verdict,
   because "Dobra lozinka" does not tell someone what is still missing. */
.ds-strength { height: 4px; border-radius: var(--radius-pill); background: var(--surface-sunken); overflow: hidden; }
.ds-strength__bar { height: 100%; width: 0; border-radius: var(--radius-pill); transition: width var(--duration-base) var(--ease-out); }
.ds-strength__bar[data-level="1"] { width: 25%;  background: var(--danger-fg); }
.ds-strength__bar[data-level="2"] { width: 50%;  background: var(--warn-fg); }
.ds-strength__bar[data-level="3"] { width: 75%;  background: var(--orange-300); }
.ds-strength__bar[data-level="4"] { width: 100%; background: var(--ok-fg); }

/* A one-time code is read back digit by digit, so it is set wide and centred rather than
   as running text. */
.ds-field[data-variant="code"] .ds-field__control { justify-content: center; }

.ds-field[data-variant="code"] .ds-field__input {
  font: var(--type-title-1);
  font-family: var(--font-mono);
  text-align: center;
  letter-spacing: 0.3em;
}

/* The QR image is sized by the page, not by the PNG the endpoint happens to produce. */
.ds-qr { display: block; width: 200px; height: 200px; margin-inline: auto; }

/* ── Avatar: a person (round) or an organisation (square), drawn from its initials ── */
.ds-avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  background: var(--avatar-1-bg);
  color: var(--avatar-1-fg);
  font: var(--type-overline);
  letter-spacing: 0;
}

.ds-avatar[data-shape="square"] { border-radius: var(--radius-sm); }
.ds-avatar[data-size="sm"] { width: 22px; height: 22px; font-size: 9.5px; }
.ds-avatar[data-size="lg"] { width: 44px; height: 44px; font-size: 14px; }

.ds-avatar[data-tone="2"] { background: var(--avatar-2-bg); color: var(--avatar-2-fg); }
.ds-avatar[data-tone="3"] { background: var(--avatar-3-bg); color: var(--avatar-3-fg); }
.ds-avatar[data-tone="4"] { background: var(--avatar-4-bg); color: var(--avatar-4-fg); }
.ds-avatar[data-tone="5"] { background: var(--avatar-5-bg); color: var(--avatar-5-fg); }
.ds-avatar[data-tone="6"] { background: var(--avatar-6-bg); color: var(--avatar-6-fg); }
.ds-avatar[data-tone="7"] { background: var(--avatar-7-bg); color: var(--avatar-7-fg); }
.ds-avatar[data-tone="8"] { background: var(--avatar-8-bg); color: var(--avatar-8-fg); }

/* ── Chip: a filter you add and remove. The pressed chip inverts to card text on an ink fill. ── */
.ds-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 34px;
  padding: 4px 12px 4px 5px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  color: var(--text-primary);
  font: var(--type-small);
  white-space: nowrap;
}

.ds-chip:not(:has(.ds-avatar)) { padding-inline-start: 12px; }
.ds-chip:hover { background: var(--grey-050); color: var(--text-primary); }
.ds-chip[aria-current="true"] {
  border-color: transparent;
  background: var(--text-primary);
  color: var(--surface-card);
  font-weight: var(--weight-semibold);
}
.ds-chip[aria-current="true"]:hover { background: var(--ink-700); color: var(--surface-card); }
.ds-chip[data-variant="dashed"] {
  border-style: dashed;
  border-color: var(--border-strong);
  background: transparent;
  color: var(--text-muted);
}
.ds-chip .ds-icon { font-size: 16px; }
.ds-chip__count { font-variant-numeric: var(--numeric-table); }

/* ── Segmented control: two to four mutually exclusive options ── */
.ds-segmented {
  display: flex;
  gap: 2px;
  margin: 0;
  padding: 3px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--grey-100);
  min-width: 0;
}

.ds-segmented__item { position: relative; display: flex; flex: 1; min-width: 0; }

.ds-segmented__option {
  display: inline-flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 36px;
  padding: 0 var(--space-6);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font: var(--type-small);
  white-space: nowrap;
  cursor: pointer;
}

.ds-segmented__option:hover { color: var(--text-primary); }
.ds-segmented__option .ds-icon { font-size: 17px; }

.ds-segmented__option[aria-current="true"],
.ds-segmented__input:checked + .ds-segmented__option {
  background: var(--surface-card);
  color: var(--accent-nav);
  font-weight: var(--weight-semibold);
  box-shadow: var(--shadow-raised);
}

/* A radio option keeps its input for the form and the keyboard; the label draws the option. */
.ds-segmented__input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.ds-segmented__input:focus-visible + .ds-segmented__option {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

/* ── Search field: the one search per screen ── */
.ds-search {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--control-height);
  padding: 0 var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}

.ds-search[data-emphasis="hero"] {
  min-height: 48px;
  border: 1.5px solid var(--accent-nav);
  border-radius: var(--radius-lg);
}

/* The input draws no outline of its own, so the ring goes on the field around it. */
.ds-search:focus-within { outline: 2px solid var(--border-focus); outline-offset: 2px; }

.ds-search__glyph { font-size: 20px; color: var(--accent-nav); }

.ds-search__input {
  flex: 1;
  min-width: 0;
  padding: var(--space-4) 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text-primary);
  font: 400 15px/1.4 var(--font-ui);
}

.ds-search__input::placeholder { color: var(--text-placeholder); }

.ds-search__key {
  padding: 3px 6px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xs);
  color: var(--text-muted);
  font: 600 11px/1 var(--font-ui);
}

/* ── Stat card: one counted fact ── */
.ds-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-7) var(--space-8);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
}

.ds-stat__label { font: var(--type-caption); color: var(--text-muted); }
.ds-stat__value { font: var(--type-title-3); font-variant-numeric: var(--numeric-table); }
.ds-stat__note { font: var(--type-caption); color: var(--text-muted); }

/* ── Progress: a native <progress>, so its value needs no style attribute ── */
.ds-progress {
  display: block;
  width: 100%;
  height: 5px;
  border: 0;
  border-radius: 3px;
  background: var(--grey-100);
  overflow: hidden;
  appearance: none;
}

.ds-progress::-webkit-progress-bar { background: var(--grey-100); border-radius: 3px; }
.ds-progress::-webkit-progress-value { background: var(--accent-nav); border-radius: 3px; }
.ds-progress::-moz-progress-bar { background: var(--accent-nav); border-radius: 3px; }
.ds-progress[data-tone="warn"]::-webkit-progress-value { background: var(--orange-300); }
.ds-progress[data-tone="warn"]::-moz-progress-bar { background: var(--orange-300); }

/* Touch sizes on phones for chips, segmented options and the search field. */
@media (max-width: 767px) {
  .ds-chip { min-height: var(--touch-target-min); }
  .ds-segmented__option { min-height: var(--touch-target-min); }
  .ds-search { min-height: var(--control-height-mobile); }
  /* 16px keeps iOS from zooming the page when the field takes focus. */
  .ds-search__input { font-size: 16px; }
}
