/* Dashboard kit: layout on top of Quiet. Tokens only (design-system check.py refuses a literal colour or font). */
.dk-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; padding-top: var(--space-2); }
.dk-titles > .ds-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 599px) { .dk-titles > .ds-title:not([data-short]) { white-space: normal; overflow: visible; } }   /* a long title wraps, whole */

/* (30 Oct 2026) data reads as written: Inter's contextual alternates draw an "x" between two digits as "×" (a client's
   SKU "SP90x200" read "SP90×200"; the text, the CSV and the search keep "x"). Off for tables (cells, heads, row names,
   in sheets too), bar names, tooltips and the filters; the body's own features (cv11, ss01) stay on */
.ds-table, .dk-bars, .ds-tip, .dk-filters, .dk-chips { font-variant-ligatures: no-contextual; }

/* tile labels wrap rather than cut ("Contribution margin" at 412 px). (r19) Tiles in a row line up part by part (label,
   value, change, n/a, spark) whatever wraps in one of them: each tile is a five-row subgrid of its row, so a change on
   two lines ("Lost 0 / No change") never pushes a neighbour's value out of line */
.dk-top .ds-tile, .dk-detail .ds-tile, .dk-sc-grid .ds-tile { display: grid; grid-row: span 5; grid-template-rows: subgrid; row-gap: 0; }
.dk-top .ds-tile > *, .dk-detail .ds-tile > *, .dk-sc-grid .ds-tile > * { grid-column: 1; min-width: 0; }
.dk-top .ds-tile-l, .dk-detail .ds-tile-l, .dk-sc-grid .ds-tile-l { grid-row: 1; align-self: end; white-space: normal; overflow: visible; }
.dk-top .ds-tile-v, .dk-detail .ds-tile-v, .dk-sc-grid .ds-tile-v { grid-row: 2; margin-top: 2px; }
.dk-top .ds-tile > .ds-delta, .dk-detail .ds-tile > .ds-delta, .dk-sc-grid .ds-tile > .dk-sc-vs { grid-row: 3; margin-top: 2px; align-self: start; }
.dk-top .dk-tile-na, .dk-detail .dk-tile-na, .dk-sc-grid .dk-tile-na { grid-row: 4; }
.dk-top .dk-spark, .dk-detail .dk-spark, .dk-sc-grid .dk-spark { grid-row: 5; align-self: end; }
/* (replication K4) a report's scorecard grid: two a row on a phone, its per_row on a desk; the comparison's value and the
   change share a line, wrapping under each other rather than cut */
.dk-sc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dk-sc-grid.dk-sc-r1 { grid-template-columns: minmax(0, 1fr); }
.dk-sc-vs { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--space-2); }
.dk-sc-vs > .ds-delta { font-size: var(--text-xs); line-height: 16px; white-space: nowrap; }
/* (replication K5) a report's target completion bars: the metric, the bar and its share, the target; two side by side on
   a desk */
.dk-tbars { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-5); }
@media (min-width: 900px) { .dk-tbars { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dk-tbar-t { margin: 0 0 var(--space-2); font-weight: 600; }
.dk-tbar-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: end; gap: var(--space-3); }
.dk-tbar-side { display: flex; flex-direction: column; min-width: 0; }
.dk-tbar-side--end { text-align: right; }
.dk-tbar-v { font-size: var(--text-l); font-weight: 500; line-height: 24px; white-space: nowrap; }
.dk-tbar-mid { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; padding-bottom: 6px; }
.dk-tbar-meter { height: 8px; border-radius: 4px; }
.dk-tbar-meter > i { border-radius: 4px; }
.dk-tbar-pct { color: var(--text-2); font-variant-numeric: tabular-nums; }
.dk-tbar-na { margin: var(--space-1) 0 0; }
/* (replication K6) a metric chooser chart: its title and two selects over the chart(s) */
.dk-mc-picks { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); margin-bottom: var(--space-3); }
.dk-mc-h { flex: 1 1 100%; margin: 0; }
.dk-mc-pick { flex: 1 1 200px; }
.dk-mc-card + .dk-mc-card { margin-top: var(--space-3); }
.dk-grain-table .dk-label { white-space: nowrap; }   /* "20 May 2026" on one line, the table scrolls on a phone */
.dk-mc-card > .ds-chart-head, .dk-spl-card > .ds-chart-head, .dk-mv-card > .ds-chart-head { margin-top: 0; align-items: flex-start; }   /* the key at the card's top, no blank strip over it */
/* (replication K11) a split chart: a line key in its series colour (--chart-1..6 in order), a chart a unit, apart */
.ds-legend > span > i.dk-line { background: var(--dk-c); }
.dk-spl-card + .dk-spl-card { margin-top: var(--space-3); }
.dk-legend { flex-wrap: wrap; }
.dk-sc-logo { display: inline-block; width: 20px; height: 20px; margin: -2px var(--space-2) 0 0; vertical-align: middle; object-fit: contain; }   /* K10: on the title's line (ds.css draws an img as a block) */
@media (min-width: 600px) { .dk-sc-r3, .dk-sc-r4, .dk-sc-r5, .dk-sc-r6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) { .dk-sc-r4, .dk-sc-r5, .dk-sc-r6 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1100px) {
  .dk-sc-r5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .dk-sc-r6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* the filter card: WHEN row, custom dates, WHICH row; chips under it */
.dk-filters { display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-2); padding: var(--space-3); }
.dk-when, .dk-dates, .dk-cdates, .dk-which { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
.dk-dates[hidden], .dk-cdates[hidden] { display: none; }
.dk-cdates-h { flex: 1 1 100%; margin: 0; }          /* the comparison's own dates: its words over the two fields */
.dk-cdates > .ds-field { flex: 1 1 150px; }
.dk-period { flex: 1 1 200px; }                      /* the period select (DESIGN 5a), as wide as Compare with */
.dk-cmp, .dk-grain { flex: 1 1 200px; }
.dk-dates > .ds-field { flex: 1 1 150px; }
.dk-dates > .ds-btn { flex: none; }
.dk-js .dk-apply { display: none; }                  /* JS applies typed dates; the button is the no-JS fallback */
.dk-which > .ds-field, .dk-what > .ds-field { flex: 1 1 220px; }
/* (kit gap 24, DESIGN 5) a filter set to a value takes two shares of its row, so the value's name fits (a 16-letter
   store name was cut in 138 px at 1280); a phone gives it the whole row (max-width 599px) */
.dk-which:has(> .ds-field + .ds-field) > .ds-field:not(.dk-model):has(option:checked:not([value=""])) { flex: 2 1 440px; }
/* (30 Oct 2026) a filter whose no-choice words are long (a client's Tableau "Core States (1,3,4,5,7,13,16)", views.long_all)
   takes the same room, so its words show whole; the words are never shortened */
.dk-which:has(> .ds-field + .ds-field) > .ds-field.dk-long { flex: 2 1 440px; }
/* Explore's WHAT row (metric, split) sits above WHEN, as a WHICH row does below it */
.dk-what { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
/* the datalist's own arrow: the magnifier already says search, and on a phone the arrow cut the placeholder to
   "All produc" (r6, 21 Oct) */
.dk-search input::-webkit-calendar-picker-indicator { display: none !important; }
/* type=search keeps 15 px for its clear button even while it is hidden: "All categories" read "All categorie" in a half row */
.dk-search input:placeholder-shown::-webkit-search-cancel-button { display: none; }
.dk-chips { margin-top: var(--space-2); }
.dk-note { display: flex; align-items: flex-start; gap: var(--space-2); margin-top: var(--space-3); color: var(--text-2); }
.dk-note > .ds-i { margin-top: 2px; color: var(--text-3); }
.dk-note > span { min-width: 0; overflow-wrap: anywhere; }   /* a 3,000-letter value in a link ran the phone page sideways (tester 3) */
/* section, chart and fold titles are headings for a screen reader; they keep the look they had as labels */
.dk-h { margin: 0; }
.dk-h-fold { font: inherit; }

/* hero + tiles: stacked on a phone, side by side on a desk */
.dk-kpi-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.dk-kpi .ds-delta { flex-wrap: wrap; }
.dk-tile-na, .ds-tile .ds-delta { white-space: normal; }
.dk-spark { display: block; height: 28px; margin-top: 6px; }
.dk-hero-s { font-size: var(--text-2xl); }
.dk-top--solo > .dk-kpi { margin-bottom: 0; }

/* the chart card */
.dk-chart-card { margin-top: var(--space-6); padding: var(--space-4); }
.dk-chart-card > .ds-chart-head { margin-top: 0; align-items: flex-start; }
.dk-chart-title { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.dk-chart { min-height: 200px; }
.ds-legend > span > i.dk-muted-key { background: var(--chart-muted); }
.dk-chart-table { margin-top: var(--space-2); }

/* tables: the system's table has no side padding, so number columns get a gap of their own */
.ds-table .num { padding-left: var(--space-4); }
.dk-phone-all .num { padding-left: 10px; }   /* (B2) a sheet of many figures to the cent: their gaps go to the name beside them; 8 px at least (ui.mjs "touching"), its first real figures read 6-7 */
/* and so do the text columns after a row's name (a label's other fields, the scorecard's dates, a check's words) */
.dk-hscroll > .ds-table td:not(.num):not(.dk-label), .dk-hscroll > .ds-table th:not(.num):not(:first-child) { padding-left: var(--space-4); }
/* a number never breaks ("−" alone above "$135,359" at 412 px: tester 1); a head breaks between words only */
.dk-fig, .ds-table td.num { white-space: nowrap; }
.ds-table th { overflow-wrap: normal; word-break: normal; hyphens: manual; }
/* DESIGN 12a: a column head is the button that sorts its table, a 44px target; the arrow marks the sorted column */
.ds-table th .dk-sort { font: inherit; color: inherit; letter-spacing: inherit; text-align: inherit; background: none; border: 0;
  padding: 0; margin: -8px 0; min-height: var(--tap); min-width: var(--tap); display: inline-flex; align-items: center; gap: 2px;
  cursor: pointer; }
.ds-table th.num .dk-sort { justify-content: flex-end; }
.ds-table th[aria-sort] { color: var(--text-2); }
.dk-sort-ar:empty { display: none; }
@media (hover: hover) { .ds-table th .dk-sort:hover { color: var(--text); } }
/* a change under its figure in the same cell (the store tables): its own line, as wide as its words, right-aligned */
.ds-table td.num > .ds-delta.dk-sub { display: table; margin-left: auto; white-space: nowrap; }
/* what a row belongs to (a campaign's channel), or that it is not one ("not a campaign"); a row's verdict */
.dk-of { display: block; }
.dk-verdict { margin-top: 2px; color: var(--text-2); white-space: normal; }
.dk-verdict-all { margin-top: var(--space-2); }
.dk-explain { margin: 0 0 var(--space-3); }
.dk-scope { text-transform: none; letter-spacing: 0; }
.dk-label { padding-right: var(--space-2); }
.dk-rows .ds-badge, .dk-label .ds-badge { margin-left: var(--space-1); vertical-align: middle; white-space: nowrap; }
.dk-rowbtn { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); width: 100%; min-height: var(--tap);
  padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.dk-rowbtn > .ds-i { color: var(--text-3); flex: none; }
.dk-collapsed tr[data-more] { display: none; }
.dk-showall { margin-top: var(--space-1); min-height: var(--tap); }
.dk-total td { font-weight: 600; }
.dk-sub { display: block; }
.ds-delta.dk-sub { display: flex; justify-content: flex-end; font-size: var(--text-xs); color: var(--text-3); }
.dk-na { margin-top: var(--space-2); }
/* (DESIGN 66) a fold's CSV button sits at the end of its own head row; the lines a table does not draw, under it */
.dk-csv-head { justify-content: flex-end; }
.dk-rows-left, .dk-rows-cut { margin-top: var(--space-2); }
.dk-chart-na > .dk-na { margin-top: var(--space-1); }
/* cohorts and lift tests: a caption under the title; the test's dates and design under its name */
.dk-caption { margin: 0 0 var(--space-2); }
.dk-tests .dk-label { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.dk-change { white-space: nowrap; }
.dk-unsold { margin: var(--space-2) 0; }
.dk-fold { margin-top: var(--space-6); }
.dk-fold > summary + * { margin-top: var(--space-2); }
.dk-defs td { vertical-align: top; padding: var(--space-3) var(--space-3) var(--space-3) 0; height: auto; }  /* 12 px: a term filling its column still clears the next cell (8 px touched at 412) */
.dk-first { margin-top: var(--space-4); }
.dk-empty { margin-top: var(--space-5); display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); }

/* series colours, tokens only: --chart-1..6 in their fixed order; a stack's calm neutrals (dk-n1..4, calmest first) step
   from the muted mark (>= 3:1 in both themes, so no segment fades into the card) towards the third text colour, and the
   one series in the accent is where the eye lands */
.dk-c1 { --dk-c: var(--chart-1); } .dk-c2 { --dk-c: var(--chart-2); } .dk-c3 { --dk-c: var(--chart-3); }
.dk-c4 { --dk-c: var(--chart-4); } .dk-c5 { --dk-c: var(--chart-5); } .dk-c6 { --dk-c: var(--chart-6); }
.dk-n1 { --dk-c: var(--chart-muted); }
/* r14 (testers 1, 2, r13): the steps ran muted -> text-3, an OKLab lightness step of 0.04: four near-identical greys
   told apart only by the gaps. Now muted -> text in equal steps: 0.13 in light and dark, each >= 3:1 on the card */
.dk-n2 { --dk-c: color-mix(in oklab, var(--chart-muted) 67%, var(--text)); }
.dk-n3 { --dk-c: color-mix(in oklab, var(--chart-muted) 33%, var(--text)); }
.dk-n4 { --dk-c: var(--text); }
/* r14 fix B: a stack of five neutrals (the P&L: cost of goods, shipping, fees, ads, operating costs) steps in quarters
   from muted to text, each step still more than 0.08 in OKLab lightness; four or fewer keep the thirds above */
.dk-n5-ramp .dk-n2 { --dk-c: color-mix(in oklab, var(--chart-muted) 75%, var(--text)); }
.dk-n5-ramp .dk-n3 { --dk-c: color-mix(in oklab, var(--chart-muted) 50%, var(--text)); }
.dk-n5-ramp .dk-n4 { --dk-c: color-mix(in oklab, var(--chart-muted) 25%, var(--text)); }
.dk-n5 { --dk-c: var(--text); }
/* a series key is a swatch (a bar's colour), not the line chart's 2px dash */
i.dk-key, .ds-legend > span > i.dk-key, .ds-tip-row > i.dk-key { flex: none; width: 10px; height: 10px; border-radius: 2px; background: var(--dk-c); }
.ds-tip-row > i.dk-key-none { background: none; }
/* a swatch as dark as the tooltip (the darkest neutral) still shows: a hairline ring of the tooltip's own text colour
   mixed into its surface, opaque, >= 3:1 against the tooltip in both themes (r15 fix C2, WCAG 1.4.11: the 45%-alpha
   ring left Ad spend and Operating costs looking like the total's empty box); the total row has no swatch at all */
.ds-tip-row > i.dk-key { box-shadow: 0 0 0 1px color-mix(in oklab, currentColor 60%, var(--text)); }
.ds-tip-row > i.dk-key.dk-key-none { box-shadow: none; }
.dk-tip-total { margin-top: 2px; }
.dk-legend { flex-wrap: wrap; row-gap: var(--space-1); }

/* bars: a row per value. Phone: the name (and share, change) on a line, the bar and its value under it; desk: one row */
.dk-bars > .dk-legend { margin: 0 0 var(--space-2); }
.dk-bar-list { list-style: none; margin: 0; padding: 0; }
/* the share and change take at most half the row (a phone: "Nothing in the comparison period" left a product's name 82 px), wrapping inside it */
.dk-bar-row { display: grid; grid-template-columns: minmax(0, 1fr) fit-content(50%); grid-template-areas: "name sub" "plot plot";
  column-gap: var(--space-3); row-gap: var(--space-1); padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.dk-bar-row:last-child { border-bottom: 0; }
.dk-collapsed > .dk-bar-row[data-more] { display: none; }
.dk-bar-name { grid-area: name; min-width: 0; font-size: var(--text-s); line-height: 20px; overflow-wrap: anywhere; }
.dk-bar-name > .ds-badge { margin-left: var(--space-1); vertical-align: middle; }
.dk-bar-sub { grid-area: sub; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--space-1);
  color: var(--text-3); min-width: 0; text-align: right; line-height: 20px; }
.dk-bar-sub > .ds-delta { font-size: var(--text-xs); }
.dk-bar-plot { grid-area: plot; display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.dk-bar-line { display: grid; grid-template-columns: minmax(0, 1fr) 8.5rem; align-items: center; gap: var(--space-3); min-height: 20px; }
.dk-bar-track { display: block; height: 8px; margin-top: 2px; border-radius: 0 4px 4px 0; background: var(--surface-2); }
/* several series: thin bars, close together, values in small type */
.dk-bar-row:not(.dk-bar-one) .dk-bar-plot { gap: 2px; }
.dk-bar-row:not(.dk-bar-one) .dk-bar-line { min-height: 18px; }
.dk-bar-row:not(.dk-bar-one) .dk-bar-track { height: 6px; }
.dk-bar-row:not(.dk-bar-one) .dk-bar-num { font-size: var(--text-xs); }
.dk-bar { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--dk-c); }
.dk-bar.is-neg { background: var(--chart-muted); }
/* r14 fix B: the comparison's bar under a row's own (conversion by device, this period against the comparison) */
.dk-bar.dk-cmp, i.dk-key.dk-cmp, .ds-legend > span > i.dk-key.dk-cmp { background: var(--chart-muted); }
.dk-bar-vs .dk-bar-track { height: 6px; }
.dk-bar-vs .dk-bar-num { font-size: var(--text-xs); color: var(--text-3); }
.dk-with { color: var(--text-3); }
.dk-bar-name > .dk-bar-btn { min-height: var(--tap); padding: 0; justify-content: flex-start; }
.dk-bar-name > .dk-bar-btn > span { flex: 1 1 auto; text-align: left; }
/* the cohort grid's thirteen months slide sideways inside its card where they do not fit, the month stays in view */
.dk-cohort-scroll { overflow-x: auto; margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4); }
.dk-cohort-scroll .dk-cohorts td:first-child, .dk-cohort-scroll .dk-cohorts th:first-child { position: sticky; left: calc(-1 * var(--space-4));
  background: var(--bg); padding-left: var(--space-4); z-index: 1; }
.dk-cohort-scroll .dk-cohorts td.dk-label { white-space: nowrap; }
/* a landing page is a path with no spaces: it breaks where it must, so a phone keeps both columns and the change under
   the sessions (r15 fix C2) */
.dk-rows[data-rows="landing"] td.dk-label { overflow-wrap: anywhere; }
/* every month's head on the same two lines, "Month" over its number (r15 fix C2: Months 0 and 10-12 wrapped while 1-9
   did not), so a 1280 px desk still shows the whole grid */
.dk-cohorts th.num .dk-age-n { display: block; }
.dk-cohorts .dk-avg-row td { border-top: 1px solid var(--line); font-weight: 600; }
.dk-cohorts .dk-avg-row .dk-of { display: block; font-weight: 400; white-space: normal; }
/* thirteen months of figures: the small size, so a 1280 px desk shows the whole grid without sliding (fork 2 UI check) */
.dk-cohorts td.num { font-size: var(--text-xs); }
.dk-cohorts .num { padding-left: var(--space-2); }
.dk-h-sub { margin: var(--space-5) 0 var(--space-2); }
.dk-views { display: inline-flex; flex-direction: column; margin-bottom: var(--space-3); min-width: 16rem; }
@media (max-width: 599px) { .dk-views { display: flex; min-width: 0; } }
.dk-hscroll { overflow-x: auto; }
.dk-hscroll > .ds-table { min-width: 100%; }
/* the box holds everything its table draws: a change's screen-reader word (.sr-only, positioned) placed past the box
   escaped its clip and widened the page (a 17-column scorecard took a desk page to 1432 px) */
.dk-hscroll { position: relative; }
/* the builder's page at the rail's foot, under More: a quiet text link (r14 fix B) */
.ds-tabbar > a.dk-hire { min-height: var(--tap); padding: 0; font-size: var(--text-xs); color: var(--text-3);
  text-decoration: underline; text-underline-offset: 2px; }
@media (hover: hover) { .ds-tabbar > a.dk-hire:hover { color: var(--text); } }
.dk-bar-num { text-align: right; font-size: var(--text-s); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dk-bar-abs { margin-left: var(--space-1); font-size: var(--text-xs); color: var(--text-3); }
@media (min-width: 600px) {
  .dk-bar-row { grid-template-columns: 12rem minmax(0, 1fr) 11rem; grid-template-areas: "name plot sub"; align-items: center; }
  .dk-bar-row:not(.dk-bar-one) { grid-template-columns: 12rem minmax(0, 1fr); grid-template-areas: "name plot"; }
  /* a long change ("Nothing in the comparison period", a product new this period) wraps in its column, never past the
     page's edge (r13 check: Explore's bars ran a 1280 px desk to 1304 px) */
  .dk-bar-sub { justify-content: flex-start; flex-wrap: wrap; white-space: normal; min-width: 0; }
}

/* a funnel: a step per row, its bar as long as its share of the first step; phone: name and count, the bar, then the
   shares in words; desk: one line */
.dk-funnel-list { list-style: none; margin: 0; padding: 0; }
.dk-funnel-step { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name num" "bar bar" "rates rates";
  column-gap: var(--space-3); row-gap: var(--space-1); padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.dk-funnel-step:last-child { border-bottom: 0; }
.dk-funnel-name { grid-area: name; min-width: 0; font-size: var(--text-s); line-height: 20px; }
.dk-funnel-num { grid-area: num; text-align: right; font-size: var(--text-s); font-weight: 600; font-variant-numeric: tabular-nums;
  white-space: nowrap; line-height: 20px; }
/* (r17) drawn as a funnel: a thick bar centred in its track, as long as its share of the first step, and behind it
   the step before's, striped: the people this step lost */
.dk-funnel-track.dk-bar-track { grid-area: bar; position: relative; height: 24px; margin: 0; border-radius: var(--radius-s);
  background: none; }
.dk-funnel-track > .dk-bar, .dk-funnel-track > .dk-funnel-gone { position: absolute; top: 0; bottom: 0; left: 50%;
  transform: translateX(-50%); border-radius: var(--radius-s); }
.dk-funnel-track > .dk-bar { height: auto; }
.dk-funnel-gone { background: repeating-linear-gradient(135deg, var(--surface-2) 0 4px, var(--line-strong) 4px 6px); }
.dk-funnel-rates { grid-area: rates; color: var(--text-3); line-height: 16px; display: flex; flex-direction: column; gap: 2px; }
.dk-funnel-left { color: var(--text-2); font-weight: 500; }
.dk-funnel-num .dk-sub { display: block; font-weight: 400; }
.dk-funnel-switch { margin: 0 0 var(--space-2); }
@media (min-width: 900px) {
  .dk-funnel-step { grid-template-columns: 9rem minmax(0, 1fr) 7.5rem 15rem; grid-template-areas: "name bar num rates"; align-items: center; }
}

/* stacked monthly columns: a card with its legend and Table switch; the running month lighter, named by its days */
.dk-months-card { padding: var(--space-4); }
.dk-months-card > .ds-chart-head { margin-top: 0; align-items: flex-start; }
.dk-months { min-height: 220px; }
.dk-seg { fill: var(--dk-c); }
/* the running month is striped (app.js draws a pattern per series): its colours stay full strength, so the steps
   still tell apart and nothing fades below 3:1 (GUIDE 1.2.7), and "striped" reads the same in both themes */
.dk-hatch-bg { fill: var(--surface); }
.dk-grid { stroke: var(--chart-grid); stroke-width: 1; }
.dk-zero { stroke: var(--chart-axis); stroke-width: 1; }
.dk-band { fill: var(--surface-2); }
.dk-hit { fill: none; pointer-events: all; outline: none; cursor: default; }
.dk-hit:focus-visible { stroke: var(--focus); stroke-width: 2; }
.dk-months-table { margin-top: var(--space-2); }
.dk-months-table .dk-total { font-weight: 600; }

/* cohorts as a heatmap: an age cell shaded by its value (data-heat 1-6), one hue, more colour = more (darker in light,
   brighter in dark); text stays text. Fix C1 (dark read faint: level 1 sat 0.047 OKLab off the page, lowest to highest
   2.45:1): 15-67% then the accent itself, which takes the page colour as its ink, so lowest to highest is 4.0:1 light
   and 4.9:1 dark, each step 0.057 or more, every figure 4.9:1 or more on its own shade (measured by ui.mjs) */
[data-heat="1"] { --dk-h: 15%; } [data-heat="2"] { --dk-h: 28%; } [data-heat="3"] { --dk-h: 41%; }
[data-heat="4"] { --dk-h: 54%; } [data-heat="5"] { --dk-h: 67%; } [data-heat="6"] { --dk-h: 100%; }
.dk-cohorts td[data-heat], .dk-heat-key > i { background: color-mix(in oklab, var(--chart-1) var(--dk-h), var(--bg)); }
.dk-cohorts td[data-heat="6"], .dk-cohorts td[data-heat="6"] * { color: var(--bg); }
.dk-cohorts .num { padding-right: var(--space-2); }
.dk-cohorts td[data-heat] { border-bottom-color: var(--bg); }
.dk-heat-key { display: inline-flex; align-items: center; gap: 2px; margin-left: var(--space-2); white-space: nowrap; vertical-align: middle; }
.dk-heat-key > i { width: 12px; height: 10px; border-radius: 2px; }
.dk-heat-key > span { margin: 0 var(--space-1); }

/* (r17) maps (Geography): land in the page colour with a hairline, so a place with no sales reads as empty (0.067 light,
   0.072 dark OKLab from level 1; the card surface sat 0.041 off it in dark); a place with a figure in the cohort grid's
   six steps of one hue, the key's own; the tooltip follows the pointer, a tap's stays until a tap elsewhere */
.dk-map-card { padding: var(--space-4); }
.dk-map-card > .ds-chart-head { margin-top: 0; flex-wrap: wrap; row-gap: var(--space-2); }
.dk-map-key { margin-left: 0; }
.dk-map-key > .dk-fig { font-size: var(--text-xs); color: var(--text-2); font-variant-numeric: tabular-nums; margin: 0 var(--space-1); }
.dk-map-wrap { position: relative; margin-top: var(--space-2); }
.dk-map { display: block; width: 100%; height: auto; overflow: visible; }
.dk-land { fill: var(--bg); stroke: var(--line-strong); stroke-width: .6px; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.dk-map-area[data-heat] { fill: color-mix(in oklab, var(--chart-1) var(--dk-h), var(--bg)); }
.dk-map-area { cursor: default; }
@media (hover: hover) { .dk-map-area:hover { stroke: var(--text); stroke-width: 1.5px; } }
.dk-map-tip { transition: none; white-space: normal; max-width: 100%; }   /* (DESIGN 22) a long tip wraps inside its chart on a phone */
.dk-map-rest { margin: var(--space-2) 0 0; }
.dk-nowrap { white-space: nowrap; }
/* (replication K12) a city map: a dot per place in the key's six steps (none: an outline), the region's states as land */
.dk-city-map { max-height: min(72vh, 640px); overflow: hidden; }    /* a zoom is taller than wide; the states past its box are cut at its edge */
.dk-map-dot { fill: var(--bg); stroke: var(--line-strong); stroke-width: .6px; vector-effect: non-scaling-stroke; cursor: default; }
.dk-map-dot[data-heat] { fill: color-mix(in oklab, var(--chart-1) var(--dk-h), var(--bg)); stroke: color-mix(in oklab, var(--chart-1) 65%, var(--bg)); }   /* the outline keeps the palest dot visible on a state in either theme */
@media (hover: hover) { .dk-map-dot:hover { stroke: var(--text); stroke-width: 1.5px; } }
.dk-map-lohi { font-size: var(--text-xs); color: var(--text-2); font-variant-numeric: tabular-nums; margin: 0 var(--space-1); }
.dk-map-unmatched { margin: var(--space-2) 0 0; }
.dk-map-table { margin-top: var(--space-2); }
/* (DESIGN 20b) the journeys Sankey (Website): each node a block tinted in its channel's series colour with a solid
   edge in it (Order the accent, No order muted) and its label inside, never on a ribbon; each ribbon a gradient from
   the channel it leaves to the one it reaches, mixed into the card (a drop-off ribbon calmer still); a hover or tap
   keeps the paths through that block or ribbon and fades the rest; the ribbons draw in once, column by column. A
   wide card draws it left to right, a narrow one top to bottom, so it never slides inside its card */
.dk-sankey-card { padding: var(--space-4); }
.dk-sankey-card > .ds-chart-head { margin-top: 0; flex-wrap: wrap; row-gap: var(--space-2); }
.dk-sankey-key { margin: var(--space-2) 0 0; }
.dk-sankey-key, .dk-uplift-card .ds-legend { flex-wrap: wrap; row-gap: var(--space-1); }
.dk-sankey-key > span, .dk-uplift-card .ds-legend > span { white-space: nowrap; }
.dk-sankey-scroll { margin-top: var(--space-3); }
.dk-sankey-wrap { position: relative; container-type: inline-size; }
.dk-sankey { display: block; width: 100%; height: auto; overflow: visible; }
.dk-sk-v { max-width: 460px; }
@container (max-width: 859px) { .dk-sk-h { display: none; } }
@container (min-width: 860px) { .dk-sk-v { display: none; } }
.dk-sankey-node { fill: color-mix(in oklab, var(--dk-c) 16%, var(--surface)); }
.dk-sk-bar { fill: var(--dk-c); pointer-events: none; }
.dk-sankey stop { stop-color: color-mix(in oklab, var(--dk-c) 50%, var(--surface)); }
.dk-sankey stop.dk-sk-off { stop-color: color-mix(in oklab, var(--dk-c) 22%, var(--surface)); }
.dk-sankey-label { font-size: 12px; fill: var(--text); pointer-events: none; }
.dk-sankey-n { fill: var(--text-2); font-variant-numeric: tabular-nums; }
.dk-sankey-head { font-size: 11px; fill: var(--text-2); letter-spacing: .04em; text-transform: uppercase; }
.dk-sk-v .dk-sankey-head { font-size: 12px; letter-spacing: 0; text-transform: none; }
.dk-sk-el { transition: opacity var(--dur) var(--ease); }
.dk-sankey.is-hl .dk-sk-el:not(.is-on) { opacity: .08; }
@media (prefers-reduced-motion: no-preference) {
  .dk-sankey.dk-sk-wait .dk-sk-links { clip-path: inset(0 100% 0 0); }
  .dk-sk-v.dk-sk-wait .dk-sk-links { clip-path: inset(0 0 100% 0); }
  .dk-sankey.dk-sk-wait.dk-sk-go .dk-sk-links { clip-path: inset(0 0 0 0);
    transition: clip-path var(--dur) var(--ease) calc(var(--j) * var(--dur)); }
}
.dk-sk-view { margin: 0; }
.dk-sankey-card .dk-flip { margin-left: auto; }
.dk-sankey-table { margin-top: var(--space-2); }
.dk-sankey-only { margin: 0 0 var(--space-2); }
/* (r17) A/B tests: each test's uplift as a dot on its 95% interval, one scale, zero drawn; accent where the interval
   clears zero, muted where it spans it, the result in words beside it. Desk: name | plot | value; phone: the name over
   the plot and the value */
.dk-uplift-card { padding: var(--space-4); }
.dk-uplift-card > .ds-chart-head { margin-top: 0; flex-wrap: wrap; row-gap: var(--space-2); }
.dk-uplift-list { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.dk-uplift-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) minmax(0, 1.4fr); gap: var(--space-1) var(--space-3);
  align-items: center; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); }
.dk-uplift-name { font-size: var(--text-s); min-width: 0; }
.dk-uplift-name .dk-sub { display: block; }
.dk-uplift-plot, .dk-uplift-axisrow { position: relative; display: block; height: 20px; }
.dk-uplift-zero { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line-strong); }
.dk-uplift-ci { position: absolute; top: 9px; height: 2px; border-radius: 1px; background: var(--chart-muted); }
.dk-uplift-dot { position: absolute; top: 4px; width: 12px; height: 12px; margin-left: -6px; border-radius: 50%;
  background: var(--chart-muted); }
.dk-uplift-row.is-sig .dk-uplift-ci, .dk-uplift-row.is-sig .dk-uplift-dot { background: var(--chart-1); }
.dk-uplift-v { display: flex; flex-direction: column; align-items: flex-end; text-align: right; font-variant-numeric: tabular-nums; }
.dk-uplift-axis { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) minmax(0, 1.4fr); gap: 0 var(--space-3); margin-top: var(--space-1); }
.dk-uplift-axisrow { grid-column: 2; height: 16px; }
.dk-uplift-tick { position: absolute; transform: translateX(-50%); white-space: nowrap; font-variant-numeric: tabular-nums; }
.dk-uplift-table { margin-top: var(--space-2); }
/* a word column after a number column keeps the number column's gap (ui.mjs: cells closer than 8 px) */
.dk-experiments td.dk-result, .dk-experiments th:last-child, .dk-uplift-table td:last-child, .dk-uplift-table th:last-child { padding-left: var(--space-4); }
.dk-experiments .dk-sub, .dk-test-sheet .dk-sub { display: block; }
.dk-hyp { margin: 0 0 var(--space-1); }
.dk-arms { margin-top: var(--space-3); }
@media (max-width: 599px) {
  .dk-uplift-row { grid-template-columns: minmax(0, 1fr) auto; }
  .dk-uplift-name { grid-column: 1 / -1; }
  .dk-uplift-axis { grid-template-columns: minmax(0, 1fr) auto; }
  .dk-uplift-axisrow { grid-column: 1; }
  .dk-uplift-v { min-width: 104px; }
}
/* (r17) a block's line to another page (Attribution -> Incrementality): a whole 44px target, wrapping on a phone */
.dk-see { margin: var(--space-2) 0 0; }
.dk-see > a { display: inline-flex; align-items: center; min-height: 44px; }

/* the More sheet */
.dk-wrap { flex-wrap: wrap; }
.dk-full { width: 100%; }
.dk-copy { width: 100%; min-height: var(--tap); padding: 0 var(--space-3); border: 0; border-radius: var(--radius-s);
  background: var(--surface-2); color: var(--text-2); font-size: var(--text-s); }
.dk-detail .ds-tiles { margin-bottom: var(--space-2); }
.dk-sheet .dk-chart-card { margin-top: var(--space-4); }
.dk-def { margin-top: var(--space-4); }

/* phone: three pages + More, two number columns; desk: every page in the rail, every column */
/* rail labels that wrap ("Profit and loss") stay centred under their icon */
.ds-tabbar > a > span { text-align: center; }
@media (max-width: 599px) {
  .ds-table .dk-wide, .dk-na.dk-wide { display: none; }
  .dk-phone-all td:not(.num):has(+ td.num) { min-width: 11rem; }   /* a sliding sheet: its last text column (a product's name) keeps room to read */
  /* (ask 30, DESIGN 30) Metric, Split by and the second metric each on a row of their own: half a row cut "No second
     metric", and a metric's own name ("Net revenue after returns" in 112 px, kit gap 19) */
  .dk-what { display: grid; grid-template-columns: minmax(0, 1fr); }
  /* a row's mark wraps inside its outline: one line ("Lowest contribution margin %") pushed By store 2px past 412 */
  .dk-rows .ds-badge, .dk-label .ds-badge { height: auto; min-height: 22px; padding-top: 2px; padding-bottom: 2px; white-space: normal;
    line-height: 1.3; }
  /* five columns of money on 412 px: a little less gap between them */
  .dk-cohorts .num { padding-left: var(--space-2); }
  /* a month per row, every series in a column: small type and a small gap so 13 months x 6 columns fit 412 px */
  .dk-months-table { font-size: var(--text-xs); }
  .dk-months-table .num { padding-left: var(--space-2); }   /* 8 px: at 4 px "$36.5K$31.8K" read as one (r13 check) */
  /* seven columns of whole words do not fit 412 px (r14: no "Contri-bution"): the table slides sideways inside its card,
     the page never does, and the month stays in view */
  .dk-scroll { overflow-x: auto; margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4); }
  .dk-scroll .dk-months-table td:first-child, .dk-scroll .dk-months-table th:first-child { position: sticky; left: calc(-1 * var(--space-4));
    background: var(--surface); padding-left: var(--space-4); }
  .dk-scroll .dk-months-table td.dk-label { white-space: nowrap; }
  /* two filters side by side, so the card leaves room for the answer on the first screen (tester 1: it took 45%) */
  .dk-which:has(> .ds-field + .ds-field) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* (kit gap 24, DESIGN 5) a filter set to a value takes the whole row, so the value's name fits: half a row cut a
     16-letter store name to 112 px; a filter showing "All ..." stays half a row */
  .dk-which:has(> .ds-field + .ds-field) > .ds-field:not(.dk-model):has(option:checked:not([value=""])) { grid-column: 1 / -1; }
  .dk-which:has(> .ds-field + .ds-field) > .ds-field.dk-long { grid-column: 1 / -1; }
}
@media (max-width: 899px) {
  .ds-tabbar > .dk-wide-only { display: none; }
  /* a page reached through More: More is the current tab, as the system marks one (accent and its 2px bar) */
  .ds-tabbar > button[data-here] { position: relative; color: var(--accent); }
  .ds-tabbar > button[data-here]::before { content: ""; position: absolute; top: calc(-1 * (var(--space-1) + 1px)); left: calc(50% - 12px);
    width: 24px; height: 2px; border-radius: 0 0 2px 2px; background: var(--accent); }
}
/* the More sheet marks the page it is on (tester 3): the accent and a ring on its icon, not colour alone */
#more a[aria-current="page"] { color: var(--accent); }
/* (replication K14) a report's nav groups: the head never shows in a phone's tab bar; in the More sheet it sits over its
   group's first row */
/* (a client's pages, 5 Nov 2026) the rail comes ahead of #view in the document so it paints with the first bytes: on a
   1.27 MB page it arrived 0.6 s after the page's first paint and the desk's grid (:has(> .ds-tabbar)) jumped sideways. The
   phone's bar still sits at the foot of its column. */
.ds-app > .ds-tabbar { order: 1; }
.ds-tabbar > .dk-nav-head { display: none; }
#more .dk-more-head { padding: var(--space-4) 0 var(--space-1); }
#more a[aria-current="page"] .ds-row-ic { color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
:root { --dk-rail-w: 112px; }   /* (DESIGN 46) the desk rail's width: the demo's longest label on one line */
/* (DESIGN 46) the desk rail holds every page (DESIGN 2) in one even rhythm: the window's height shared by its rows
   (--dk-rail-n, the server's count) after the small gaps that open each group (data-rail-gap, --dk-rail-gaps), from
   56 px down to 36 px, so 17 rows, More and Hire me fit 1280 x 720; More follows the last group, never pinned to the
   foot with a hole above it; wide enough that every label sits on one line ("Profit and loss", "Incrementality") */
@media (min-width: 900px) {
  .ds-app:not(.ds-app--phone):has(> .ds-tabbar) { grid-template-columns: var(--dk-rail-w) 1fr; }
  .ds-app:not(.ds-app--phone) > .ds-tabbar {
    --dk-rail-gap: var(--space-3);
    --dk-rail-head: 16px;
    --dk-rail-row: clamp(36px, calc((100dvh - 2 * var(--space-2) - var(--dk-rail-gaps, 0) * var(--dk-rail-gap)
      - var(--dk-rail-heads, 0) * var(--dk-rail-head)) / var(--dk-rail-n, 16)), 56px);
    gap: 0; padding-top: var(--space-2); padding-bottom: var(--space-2); overflow-y: auto; }
  .ds-app:not(.ds-app--phone) > .ds-tabbar > a, .ds-app:not(.ds-app--phone) > .ds-tabbar > button {
    min-height: 0; height: var(--dk-rail-row); flex: none; gap: 2px; }
  .ds-app:not(.ds-app--phone) > .ds-tabbar > [data-rail-gap] { margin-top: var(--dk-rail-gap); }
  .ds-app:not(.ds-app--phone) > .ds-tabbar > a > span, .ds-app:not(.ds-app--phone) > .ds-tabbar > button > span {
    white-space: normal; text-wrap: balance; overflow-wrap: anywhere; hyphens: auto; line-height: 16px; }
  /* a page named longer than the rail (a client's own view names, "Datasheet - Order Details") takes two lines, never
     cut; one word wider than the rail ("Verpackungsregister") breaks, with a hyphen where the language has one */
  /* the icon gives way first in the shortest windows: icon, 2 px and a 16 px line in a row of 36 px */
  .ds-app:not(.ds-app--phone) > .ds-tabbar .ds-i { width: min(20px, calc(var(--dk-rail-row) - 18px));
    height: min(20px, calc(var(--dk-rail-row) - 18px)); }
  /* (replication K14) a nav group's head over its first tab, in the group gap's place (counted out of the rows' share) */
  .ds-app:not(.ds-app--phone) > .ds-tabbar > .dk-nav-head { display: block; flex: none; height: var(--dk-rail-head);
    text-align: center; white-space: nowrap; overflow: hidden; }
  /* the Hire me link right under More (r14 fix B), in the same rhythm */
  .ds-app:not(.ds-app--phone) > .ds-tabbar > a.dk-hire { margin-top: 0; }
}
@media (min-width: 900px) {
  .dk-narrow-only { display: none; }
  /* the title starts where the 1080 px content column starts; the bar's background stays full width */
  .dk-topbar { padding-left: max(var(--space-5), calc((100% - var(--content-wide)) / 2 + var(--space-5)));
    padding-right: max(var(--space-2), calc((100% - var(--content-wide)) / 2 + var(--space-2))); }
  /* the row keeps the hero's own distance from the filters: tiles taller than the hero (a reason under an n/a) touched the card */
  .dk-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr); gap: var(--space-5); align-items: end; margin-top: var(--space-6); }
  .dk-top > .dk-kpi { margin-top: 0; margin-bottom: 0; }
  .dk-top--solo { grid-template-columns: minmax(0, 1fr); }
  /* WHEN on one row, WHICH fields side by side under it; a page with a single filter keeps it on the WHEN row */
  .dk-when, .dk-which, .dk-what { flex-wrap: nowrap; }
  /* (kit gap 24, DESIGN 5) the WHICH row wraps, every field kept at 220 px or more, when it holds six fields (Explore:
     "All products" cut in 159 px) or a filter set to a value, whose field takes two shares (above) */
  .dk-which:has(> .ds-field:nth-child(6)),
  .dk-which:has(> .ds-field + .ds-field):has(> .ds-field:not(.dk-model) option:checked:not([value=""])),
  .dk-which:has(> .ds-field + .ds-field):has(> .ds-field.dk-long) { flex-wrap: wrap; }
  .dk-filters:has(> .dk-which > .ds-field:only-child) { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
  .dk-filters:has(> .dk-which > .ds-field:only-child) > .dk-when { flex: 2 1 520px; }
  .dk-filters:has(> .dk-which > .ds-field:only-child) > .dk-which { flex: 1 1 260px; }
  /* Explore's WHAT keeps a row of its own there: beside WHEN it shrank to "Operating profit befo" (r15 fix C2) */
  .dk-filters:has(> .dk-which > .ds-field:only-child) > .dk-what { flex: 1 1 100%; }
  .dk-dates { flex: 1 1 100%; }
}
.dk-skel { height: 240px; border-radius: var(--radius-m); }

/* ---- (r18) the gate: the sign-in page, /privacy, and the photo card (a card in the corner on a desk, a slim bar above
   the tab bar on a phone, never a modal; GUIDE rule 6: a hairline, no shadow) ---- */
.dk-gate { display: flex; min-height: 100vh; min-height: 100dvh; align-items: center; justify-content: center;
  padding: var(--space-5) var(--space-4); }
.dk-gate-card { width: 100%; max-width: 400px; display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  padding: var(--space-6) var(--space-5); text-align: center; }
.dk-gate-photo { width: 96px; height: 96px; border-radius: 50%; object-fit: cover; }
.dk-gate-name { margin: 0; }
.dk-gate-line, .dk-gate-why, .dk-gate-err { margin: 0; }
.dk-gate-line { color: var(--text-2); }
.dk-gate-err { color: var(--text); font-weight: 600; }
.dk-gate-actions { width: 100%; display: flex; flex-direction: column; gap: var(--space-3); margin-top: var(--space-2); }
.dk-gate-email { display: flex; flex-direction: column; gap: var(--space-2); text-align: left; }
.dk-gate-privacy { min-height: var(--tap); min-width: var(--tap); display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-2); }
.dk-gate-hire { margin-left: var(--space-4); }    /* (6c fix 4) the wall's way to the owner, beside Privacy */
/* (DESIGN 25) the sign-in card over the page asked for: the welcome card's look and motion; the page behind stays drawn,
   blurred under a scrim of its own background token (never pure black or white), not scrollable; nothing moves under
   prefers-reduced-motion. Without script the card is drawn open in place (fixed, centred), the page still inert. */
body.dk-walled { overflow: hidden; }
body.dk-walled > .ds-app { filter: blur(6px); }
.dk-wall { position: fixed; inset: 0; z-index: 60; max-height: calc(100% - 2 * var(--space-4)); overflow: auto;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.dk-wall:not([open]) { display: none; }
dialog.dk-wall::backdrop { background: color-mix(in srgb, var(--bg) 55%, transparent); }
.dk-wall .dk-gate-name { margin: 0; }
.dk-wall .dk-gate-actions, .dk-wall .dk-gate-retry, .dk-wall .dk-gate-email { width: 100%; }
.dk-gate-to { color: var(--text); font-weight: 600; word-break: break-all; }
.dk-gate-retry > summary { min-height: var(--tap); }
.dk-gate-retry .dk-gate-email { margin-top: var(--space-2); }
.dk-gate-fixrow { display: contents; }
.dk-gate-body.dk-walled { background: var(--bg); }
@media (prefers-reduced-motion: no-preference) {
  body.dk-walled > .ds-app { animation: dk-wall-blur var(--dur) var(--ease); }
  dialog.dk-wall::backdrop { animation: ds-fade var(--dur) var(--ease); }
  @keyframes dk-wall-blur { from { filter: none; } }
}
.dk-privacy { line-height: 1.5; }
.dk-privacy .ds-h { margin-top: var(--space-5); }
.dk-privacy ul { padding-left: var(--space-5); }
.dk-privacy .ds-btn { margin-top: var(--space-5); }
/* (r20) the photo card sits in the sticky top bar's band, at its right, on a desk (6c: a phone's is a strip over the tab
   bar, below): a card never covers a figure (r19: the desk's corner card lay on Incrementality's Amazon Ads row and Customers' monthly bars at 1280 x 900;
   the phone's bar above the tab bar on whatever scrolled under it). The titles keep clear of it (app.js: --dk-card-room) */
.dk-card { position: fixed; z-index: 4; top: calc(env(safe-area-inset-top) + 5px); right: var(--space-2); display: flex;
  align-items: center; gap: var(--space-2); max-width: 320px; padding: 0 0 0 var(--space-2);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-m); }
.dk-card-photo { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex: none; }
.dk-card-text { margin: 0; font-size: var(--text-s); white-space: nowrap; }
.dk-card-text a { display: inline-flex; min-height: var(--tap); align-items: center; color: var(--accent); }
.dk-card-text a + a { margin-left: var(--space-3); }   /* (DESIGN 35) Book a call beside Ask me */
.dk-card-x { flex: none; margin-left: auto; }
@media (min-width: 900px) { body.dk-card-on .dk-topbar { padding-right: var(--dk-card-room, 340px); } }
@media (prefers-reduced-motion: no-preference) {
  .dk-card { animation: dk-card-in var(--dur) var(--ease); }
  @keyframes dk-card-in { from { transform: translateY(-8px); } }
}
@media (min-width: 900px) {   /* its right edge on the content column's, as the title's left edge is */
  .dk-card { right: max(var(--space-2), calc((100vw - var(--dk-rail-w) - var(--content-wide)) / 2 + var(--space-2))); }
}
/* (6c fix 3, r16's phone plan) below 900 px the card leaves the top bar, which keeps every title and Hire me: a slim
   strip across the screen right over the tab bar, a hairline on top, the content's end padded clear of it; app.js holds
   it back while the consent bar, which sits there too, is on */
@media (max-width: 899px) {
  .dk-card { top: auto; left: 0; right: 0; bottom: calc(56px + var(--space-1) + var(--space-2) + 1px + env(safe-area-inset-bottom));
    max-width: none; padding: 0 var(--space-2) 0 var(--space-4); border: 0; border-top: 1px solid var(--line); border-radius: 0; }
  .dk-card-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  body.dk-card-on .ds-main { padding-bottom: calc(var(--space-7) + 46px); }
}
@media (max-width: 599px) {   /* (DESIGN 35) a phone's card: the face, the question and Ask me, no Book a call */
  .dk-card-text a.dk-card-book { display: none; }
  .dk-card-photo { width: 28px; height: 28px; }
}

/* (r20) the welcome card: centred over the system's scrim, a fade and a short rise over the motion token, the chips one
   after another (40 ms), the chosen chip in the accent; nothing moves under prefers-reduced-motion */
.dk-welcome { width: min(360px, calc(100% - 2 * var(--space-4))); margin: auto; padding: var(--space-6) var(--space-5) var(--space-4);
  background: var(--surface); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius-l); text-align: center; }
/* (r20 QA) the greeting is the card's title line at heading size, the question under it at body size; the scrim is the
   sheet's (the UA's default backdrop was invisible in dark); focus lands on the card itself, never on a chip (a ring on
   Founder read as a pre-chosen answer); the chips two by two on a phone, one row on a desk (they wrapped 3 + 1) */
.dk-welcome:focus, .dk-welcome:focus-visible { outline: none; }
.dk-welcome::backdrop { background: var(--scrim); }
.dk-welcome.is-leaving::backdrop { opacity: 0; }
.dk-welcome-hi { margin: 0; font-size: var(--text-xl); font-weight: 500; letter-spacing: -.01em; line-height: 1.25; color: var(--text); }
.dk-welcome .dk-welcome-ask { margin: var(--space-1) 0 var(--space-5); font-size: var(--text-m); font-weight: 400; color: var(--text-2); }
.dk-welcome-chips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 var(--space-2); }
.dk-welcome-chips > .ds-chip { justify-content: center; }
@media (min-width: 900px) {
  .dk-welcome { width: min(440px, calc(100% - 2 * var(--space-4))); }
  .dk-welcome-chips { grid-template-columns: repeat(4, auto); justify-content: center; }
}
.dk-welcome .ds-chip.is-chosen { background-color: var(--accent); color: var(--on-accent); }
.dk-welcome-skip { margin-top: var(--space-4); }
.dk-welcome.is-leaving { opacity: 0; transform: translateY(4px); }
@media (prefers-reduced-motion: no-preference) {
  .dk-welcome::backdrop { animation: ds-fade var(--dur) var(--ease); transition: opacity var(--dur) var(--ease); }
  .dk-welcome { transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
  .dk-welcome[open] { animation: dk-welcome-in var(--dur) var(--ease); }
  .dk-welcome[open] .dk-welcome-chips > * { animation: dk-welcome-chip var(--dur) var(--ease) backwards; }
  .dk-welcome-chips > :nth-child(2) { animation-delay: 40ms; }
  .dk-welcome-chips > :nth-child(3) { animation-delay: 80ms; }
  .dk-welcome-chips > :nth-child(4) { animation-delay: 120ms; }
  .dk-welcome-chips > :nth-child(5) { animation-delay: 160ms; }
  .dk-welcome .ds-chip { transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease); }
  @keyframes dk-welcome-in { from { opacity: 0; transform: translateY(8px); } }
  @keyframes dk-welcome-chip { from { opacity: 0; transform: translateY(4px); } }
}
/* a role's page reached through More on a desk: More is the current rail entry, as on a phone (accent and its bar) */
@media (min-width: 900px) {
  .ds-app:not(.ds-app--phone) > .ds-tabbar > button[data-here-desk] { position: relative; color: var(--accent); }
  .ds-app:not(.ds-app--phone) > .ds-tabbar > button[data-here-desk]::before { content: ""; position: absolute; top: calc(50% - 12px);
    left: calc(-1 * var(--space-2)); width: 2px; height: 24px; border-radius: 0 2px 2px 0; background: var(--accent); }
}
/* a role's five-slot phone bar: "Profit and loss" wraps to two lines there, so every icon starts on one row (centred,
   the wrapped label lifted its icon 9 px above the others) */
@media (max-width: 899px) {
  .ds-tabbar[data-role]:not([data-role=""]) > a, .ds-tabbar[data-role]:not([data-role=""]) > button {
    justify-content: flex-start; padding-top: var(--space-3); }
}
/* (r20) the MMM's response curves (Incrementality): one card per ad channel, side by side on a desk and stacked on a
   phone; the curve in the accent, break-even a dashed muted line, today's spend a dot on a hairline, the point where the
   next dollar falls to break-even a ring; a tenth of the spend under the pointer or the finger answers in the tooltip */
.dk-curves { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); margin-top: var(--space-2); }
@media (min-width: 960px) { .dk-curves { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.dk-curve-key { flex-wrap: wrap; row-gap: var(--space-1); }
.dk-curve-key > span { white-space: nowrap; }
.dk-curve-card { padding: var(--space-4); min-width: 0; }
.dk-curve-card > .ds-chart-head { margin-top: 0; align-items: flex-start; }
.dk-curve-head { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dk-curve-wrap { position: relative; margin-top: var(--space-2); }
.dk-curve { display: block; width: 100%; height: auto; overflow: visible; }
.dk-curve-grid { stroke: var(--chart-grid); stroke-width: 1px; shape-rendering: crispEdges; }
.dk-curve-ax { font-size: calc(var(--text-xs) / var(--dk-k, 1)); fill: var(--text-3); font-variant-numeric: tabular-nums; }
/* (DESIGN 22) app.js sets --dk-k, the drawing's scale on its card: lines keep 2px whatever the card's width */
.dk-curve path, .dk-curve line, .dk-curve circle { vector-effect: non-scaling-stroke; }
.dk-curve-line { fill: none; stroke: var(--chart-1); stroke-width: 2px; stroke-linejoin: round; stroke-linecap: round; }
.dk-curve-be { stroke: var(--chart-muted); stroke-width: 1.5px; stroke-dasharray: 4 4; }
.dk-curve-mark { stroke: var(--chart-axis); stroke-width: 1px; shape-rendering: crispEdges; }
.dk-curve-today { fill: var(--chart-1); stroke: var(--surface); stroke-width: 2px; }
.dk-curve-stop { fill: var(--surface); stroke: var(--text); stroke-width: 2px; }
.dk-curve-hit { fill: none; pointer-events: all; cursor: default; }
@media (hover: hover) { .dk-curve-hit:hover { fill: color-mix(in oklab, var(--chart-1) 10%, var(--surface)); fill-opacity: .5; } }
.dk-curve-words { margin: var(--space-2) 0 0; }
.dk-curve-table { margin-top: var(--space-2); }
i.dk-key.dk-key-dash, .ds-legend > span > i.dk-key.dk-key-dash { height: 0; border-radius: 0; background: none; border-top: 2px dashed var(--chart-muted); }
i.dk-key.dk-key-ring, .ds-legend > span > i.dk-key.dk-key-ring { border-radius: 50%; background: var(--surface); box-shadow: inset 0 0 0 2px var(--text); }
i.dk-key.dk-key-tick, .ds-legend > span > i.dk-key.dk-key-tick { width: 2px; border-radius: 0; background: var(--line-strong); }
/* (r20) the budget-shift what-if: money moved, each channel's change in sales caused, the net in bold */
.dk-shift-lead { margin: 0 0 var(--space-2); }
/* (r20 batch 3, B1) the AI page: who answered, under the player (DESIGN 48: no date), an answer's numbers links whose box is a 44 px target
   while the line keeps its height, the MCP calls in scroll boxes that never run the page sideways; then the visitor's
   connector URL beside its Copy button and the apps' steps */
.dk-ai-said { margin: 0; }
.dk-ask, .dk-ask-use { max-width: 720px; }
/* inline, so a line never breaks between "(" and its number (an inline-block let "(" end a line); its padding makes
   the box a 44 px target without moving a character: vertical padding on an inline box leaves the line alone, and the
   negative side margins take back the horizontal */
a.dk-ask-fig { padding: 13px 14px; margin: 0 -14px; white-space: nowrap; text-decoration-thickness: 1px; }
a.dk-ask-fig:focus-visible { outline-offset: -11px; }
.dk-ask-call-list { list-style: none; margin: 0; padding: 0; }
.dk-ask-call { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-2) 0 var(--space-3); min-width: 0; }
.dk-ask-call + .dk-ask-call { border-top: 1px solid var(--line); }
.dk-ask-tool { font-weight: 500; }
.dk-json { margin: 0 0 var(--space-2); max-height: 240px; overflow: auto; padding: var(--space-3); border-radius: var(--radius-s);
  background: var(--surface-2); color: var(--text-2); font-family: var(--font-sans); font-size: var(--text-xs); line-height: 18px;
  white-space: pre; tab-size: 2; }
.dk-ask-url { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); align-items: end; }
.dk-ask-apps { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); margin-top: var(--space-2); }
@media (min-width: 900px) { .dk-ask-apps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dk-ask-app-h { margin: 0 0 var(--space-2); font-size: var(--text-s); font-weight: 500; }
ol.dk-steps { margin: 0; padding-left: var(--space-5); list-style: decimal; color: var(--text-2); font-size: var(--text-s); line-height: 22px; }
/* (DESIGN 26) AI: the replay frame (a fixed-height chat window, the asked question on the right, the connector step,
   the answer streaming in word by word), its caption and pause button; then the questions fold (DESIGN 52), connect
   tabs, code with Copy */
.dk-ai-loop { margin: var(--space-4) 0 0; }
.dk-ai-chat { padding: 0; overflow: hidden; }
.dk-ai-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line); font-size: var(--text-s); }
.dk-ai-head .ds-i { color: var(--accent); }
/* (DESIGN 38) as tall as the tallest conversation finished (app.js sets the height): nothing scrolls inside it */
.dk-ai-scroll { position: relative; overflow: hidden; padding: var(--space-4); }
.dk-ai-q { display: flex; justify-content: flex-end; margin: 0 0 var(--space-3); }
.dk-ai-qt { max-width: 85%; padding: var(--space-2) var(--space-3); border-radius: var(--radius-m); background: var(--surface-2);
  font-size: var(--text-s); line-height: 20px; overflow-wrap: anywhere; }
.dk-ai-tool { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-3); }
.dk-ai-a { font-size: var(--text-s); line-height: 1.55; overflow-wrap: anywhere; }
.dk-ai-a p, .dk-ai-a ul { margin: 0 0 var(--space-3); }
.dk-ai-a ul { padding-left: var(--space-5); }
.dk-ai-a b { font-weight: 600; }
.dk-ai-a a.dk-ask-fig { padding-top: 14px; padding-bottom: 14px; }   /* 14 px type: 44 px targets, the line unmoved */
.dk-ai-loop [data-off] { display: none; }
.dk-ai-cap { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-1); }
/* (DESIGN 42) two labelled parts in the one heading style, a line under each; a clear break above Connect */
.dk-ai-sub { margin: var(--space-1) 0 var(--space-3); }
.dk-ai-connect { margin-top: var(--space-8); padding-top: var(--space-6); border-top: 1px solid var(--line); }
/* (DESIGN 39) a conversation's chart under its short answer: the kit's line, or bars with each value beside its bar */
.dk-ai-viz { margin: var(--space-1) 0 0; }
.dk-ai-viz-h { margin: 0 0 var(--space-2); }
.dk-chart.dk-ai-trend { min-height: 150px; }
.dk-ai-bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.dk-ai-bar { display: grid; grid-template-columns: minmax(0, 8rem) minmax(0, 1fr) auto; align-items: center; gap: var(--space-3);
  min-height: 24px; font-size: var(--text-s); }
.dk-ai-bar-name { line-height: 18px; overflow-wrap: anywhere; }
.dk-ai-bar > .dk-bar-track { margin-top: 0; }
.dk-ai-bar-num { min-width: 3.5rem; text-align: right; color: var(--text-2); }
.dk-ai-how { margin-top: var(--space-2); padding-left: 0; padding-right: 0; }
/* (DESIGN 41) every question a chip, grouped by role, under the player; a phone stacks a role over its chips */
.dk-ai-chips { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-4); }
.dk-ai-role { display: flex; flex-direction: column; }
@media (min-width: 900px) {
  .dk-ai-role { display: grid; grid-template-columns: 6rem minmax(0, 1fr); align-items: start; column-gap: var(--space-3); }
  .dk-ai-role-h { padding-top: 13px; }
}
/* a question that wraps (the two long ones at 412) grows its pill: 8 px above and below the text keep it inside the pill
   it draws (the chip's 4 px transparent borders belong to its 44 px target, not to the pill); a one-line chip stays 44 px */
.dk-ai-chip { white-space: normal; text-align: left; line-height: 18px; padding-block: var(--space-2); }
.dk-ai-sheet-q { margin: 0 0 var(--space-2); }
.dk-ai-sheet-h { margin: var(--space-4) 0 var(--space-2); }
.dk-ai-try-more { margin-top: var(--space-2); }
.dk-ai-play { flex: none; }
.dk-ai-capt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dk-ai-apps { margin: var(--space-4) 0 var(--space-3); max-width: 100%; overflow-x: auto; }
.dk-ai-pane .ds-small { margin: var(--space-3) 0 0; }
.dk-ai-code { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-2); align-items: start; margin-top: var(--space-3); }
.dk-ai-code .dk-json { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.dk-ai-docs { margin: var(--space-2) 0 0; overflow-wrap: anywhere; }
.dk-ai-docs a { display: inline-flex; align-items: center; min-height: var(--tap); }
.dk-ai-try-fold { margin: 0 0 var(--space-4); }
.dk-ai-try { margin-bottom: var(--space-2); }
.dk-ai-note { margin: var(--space-3) 0 0; }
.dk-ask-anon { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
/* (DESIGN 31) the expertise line atop Attribution, Incrementality, A/B tests, Explore and Customers; Work with me: photo, two parts, Hire me */
.dk-expert { margin: var(--space-6) 0 var(--space-5); color: var(--text-2); }   /* the room the link's tall box used to take: the page below stays put (20 px collapses with the card's 8) */
/* (DESIGN 45, 43) a link inside running text (Work with me here, the Alerts intro's See the agent) stays inline, so its
   paragraph keeps one line pitch whether or not the link shares a line: 14 px padding around 14 px type makes the box a
   44 px target without growing its line box (as the AI answers' number links), the side padding taken back by a
   negative margin, the focus ring drawn back to the words */
.dk-expert a, a.dk-al-agent { padding: 14px; margin: 0 -14px; white-space: nowrap; }
.dk-expert a > .ds-i, a.dk-al-agent > .ds-i { display: inline; margin-left: var(--space-1); vertical-align: middle; }   /* ds.css draws an svg as a block */
.dk-expert a:focus-visible, a.dk-al-agent:focus-visible { outline-offset: -11px; }
/* (r20 batch 3, B4) Every number checked: sources, the warehouse and this dashboard as three steps (down a phone,
   across a desk), then the last live run's counts as rows */
.dk-flow { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
.dk-flow-step { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--space-4); min-width: 0; }
.dk-flow-to { display: grid; place-items: center; color: var(--text-3); }
.dk-flow-src { list-style: none; margin: var(--space-1) 0 0; padding: 0; font-size: var(--text-s); }
.dk-flow-src > li { display: flex; justify-content: space-between; gap: var(--space-3); padding: 6px 0; border-bottom: 1px solid var(--line); }
.dk-flow-src > li:last-child { border-bottom: 0; }
.dk-flow-src .num { color: var(--text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
@media (min-width: 900px) {
  .dk-flow { grid-template-columns: minmax(0, 1.4fr) auto minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; }
  .dk-flow-to > .ds-i { transform: rotate(-90deg); }
}
.dk-run { max-width: 720px; }   /* a list: the content column (GUIDE layout), the flow below it may go wide */
.dk-run-meta { margin: 0 0 var(--space-2); overflow-wrap: anywhere; }
.dk-run-parts .ds-row-main > span, .dk-run-parts .ds-row-end { font-variant-numeric: tabular-nums; }
.dk-run-parts .ds-row-end { font-weight: 400; color: var(--text-2); font-size: var(--text-s); }
/* (r20 B5) month to date against target, under the hero: one row per metric, the figure, the system meter and its legend */
.dk-pace-when { margin: 0 0 var(--space-2); }
.dk-pace { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.dk-pace-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-2); }
.dk-pace-l { font-size: var(--text-s); color: var(--text-2); }
.dk-pace-v { font-size: var(--text-l); font-weight: 600; }
.dk-pace-words { margin: var(--space-1) 0 0; }
@media (min-width: 900px) { .dk-pace { grid-template-columns: 1fr 1fr; gap: var(--space-6); } }

/* (r20 B2) the alerts page: the digest as a chat message in the system's own tokens (not Slack's brand), then the alerts
   the rules fired and the rules themselves */
.dk-msg-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.dk-msg-av { width: 36px; height: 36px; border-radius: var(--radius-s); background: var(--surface-2); color: var(--text-2);
  display: inline-grid; place-items: center; box-shadow: inset 0 0 0 1px var(--line); }
.dk-msg-text { margin: 0 0 var(--space-2); }
ul.dk-msg-list { list-style: none; margin: 0 0 var(--space-4); padding: 0 0 0 var(--space-3); border-left: 2px solid var(--line-strong);
  display: grid; gap: var(--space-3); }
.dk-msg-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-3); align-items: baseline; }
.dk-msg-l { font-size: var(--text-s); color: var(--text-2); min-width: 0; }
.dk-msg-v { text-align: right; white-space: nowrap; font-weight: 600; }
.dk-msg-v > .ds-delta { font-weight: 400; margin-left: var(--space-1); }
.dk-msg-pace { grid-column: 1 / -1; }
.dk-msg-link { display: inline-flex; align-items: center; min-height: 44px; }
.dk-alerts-from { margin: 0 0 var(--space-2); }
ul.dk-alerts { padding: var(--space-1) var(--space-4); }   /* over ds.css's ul[class] { padding: 0 } */
.dk-alert { padding: var(--space-3) 0; box-shadow: inset 0 1px 0 var(--line); }
.dk-alert:first-child { box-shadow: none; }
.dk-collapsed > li[data-more] { display: none; }
.dk-alert-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); }
.dk-alert-head > .ds-delta { white-space: nowrap; }
.dk-alert-sub { margin: 0; }
.dk-alert-go { display: inline-flex; align-items: center; min-height: 44px; min-width: 0; }
ul.dk-rules { margin: 0; padding: var(--space-1) var(--space-4); }
.dk-rule { padding: var(--space-3) 0; box-shadow: inset 0 1px 0 var(--line); }
.dk-rule:first-child { box-shadow: none; }
.dk-rule-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.dk-rule > p { margin: var(--space-1) 0 0; }
ul.dk-msg-list { max-width: 560px; }   /* a message reads as one: its figures near their labels on a desk */
/* (DESIGN 28) the Alerts intro, then the newest alert as it arrives, a Slack message or an email by the switch: the same
   chat card as the digest, and an email card with its from line and subject */
.dk-al-intro { margin: 0 0 var(--space-4); max-width: 640px; }
.dk-al-prev .ds-section-head { flex-wrap: wrap; gap: var(--space-2); }
.dk-al-top, .dk-al-prev { max-width: 640px; }
.dk-mail-from { margin: 0 0 var(--space-2); }
.dk-mail-subj { margin: 0 0 var(--space-2); font-weight: 600; }
.dk-mail-subj .ds-delta { font-weight: 400; }
/* (DESIGN 47, 54) the agents page: its intro, then a Slack channel in the AI page's player (each message its sender's
   mark, name and time, the text, Slack's Approve / Edit / Ignore drawn on one waiting for an OK, its link on a line of
   its own); (DESIGN 63) then Since midnight and the close */
.dk-ag-top, .dk-ag-slack, .dk-ag-night, .dk-ag-close { max-width: 720px; }
.dk-ag-intro { margin: 0 0 var(--space-4); }
.dk-sl-chan { font-weight: 600; }
.dk-sl-msg { display: grid; grid-template-columns: 36px minmax(0, 1fr); column-gap: var(--space-3); margin: 0 0 var(--space-3); }
.dk-sl-av { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-s);
  background: var(--surface-2); color: var(--text-2); font-size: var(--text-s); font-weight: 600; }
.dk-sl-msg[data-from="agent"] .dk-sl-av { color: var(--accent); }
.dk-sl-body { min-width: 0; }
.dk-sl-who { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); margin: 0; font-size: var(--text-s); line-height: 20px; }
.dk-sl-who > b { font-weight: 600; }
.dk-sl .dk-ai-q { display: block; margin: 0; }
.dk-sl .dk-ai-qt { display: block; max-width: none; padding: 0; border-radius: 0; background: none; }
.dk-sl .dk-ai-tool { margin: 0 0 var(--space-3) calc(36px + var(--space-3)); }
/* (6c fix 2) a channel reads from its top, so a short thread is in view at once (it sat at the foot of a box sized for
   the longest); the frame fits one view (app.js), so a long thread scrolls inside it, the newest line kept in view */
.dk-sl .dk-ai-scroll { overflow-y: auto; overscroll-behavior: contain; }
.dk-sl .dk-ai-a { line-height: 20px; }
.dk-sl .dk-ai-a p { margin: 0; }
ol.dk-sl-thread { list-style: none; margin: 0; padding: 0; }
.dk-sl-text { font-size: var(--text-s); line-height: 20px; }
/* a block, not a flex box: the replay splits its words into spans, and a flex box drops the spaces between them */
.dk-sl-link { display: block; width: max-content; max-width: 100%; padding: 12px 0; font-size: var(--text-s); line-height: 20px; }
.dk-sl .dk-msg-acts { margin: var(--space-2) 0 0; }
/* (DESIGN 63) Behind it, under the channel: four cells (two by two on a phone), each holding every thread's value in
   one grid place, only the playing thread's shown, so the strip is one height whatever plays and the chips under it
   never move (60); app.js fills Knowledge and Tools with the working step (data-fill 1), Checked and Cost with the
   agent's reply (2) */
.dk-ag-behind { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3) var(--space-4); margin: var(--space-2) 0 0;
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-m); box-shadow: inset 0 0 0 1px var(--line); }
.dk-ag-bh { min-width: 0; }
.dk-ag-bh > dt { margin: 0 0 2px; line-height: 16px; }
.dk-ag-bh-v { display: grid; margin: 0; font-size: var(--text-s); line-height: 20px; overflow-wrap: anywhere; }
.dk-ag-bh-v > span { grid-area: 1 / 1; visibility: hidden; }
.dk-ag-bh-v > span.is-on { visibility: visible; }
.dk-ag-behind[data-fill="0"] .dk-ag-bh-v > span,
.dk-ag-behind[data-fill="1"] [data-cell="checked"] .dk-ag-bh-v > span,
.dk-ag-behind[data-fill="1"] [data-cell="cost"] .dk-ag-bh-v > span { visibility: hidden; }
.dk-ag-cost, .dk-ag-hand { display: block; }
.dk-ag-cost { font-weight: 600; }
/* on a phone two by two, and under the caption, one scroll down: the frame, its caption and Pause keep the view a
   first-time visitor lands on (6d fix 1), the channel as tall as that view allows */
@media (max-width: 899px) {
  .dk-sl.dk-ai-loop { display: flex; flex-direction: column; }
  .dk-sl.dk-ai-loop > .dk-ag-behind { order: 1; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* (DESIGN 63) Since midnight: the week first, in body colour; one row a job, its time, the job (a muted note under it)
   and its level in a badge at the row's end (an outline for advice); then the close, its line and the one primary button */
ol.dk-ag-jobs { list-style: none; margin: 0; padding: var(--space-1) var(--space-4); }
ol.dk-ag-jobs > li { display: grid; grid-template-columns: 3rem minmax(0, 1fr) auto; align-items: start; gap: var(--space-3);
  padding: var(--space-3) 0; box-shadow: inset 0 1px 0 var(--line); }
ol.dk-ag-jobs > li:first-child { box-shadow: none; }
.dk-ag-at { line-height: 20px; }
.dk-ag-job { margin: 0; min-width: 0; font-size: var(--text-s); line-height: 20px; }
.dk-ag-job > span { display: block; }
.dk-ag-lv { white-space: nowrap; }
.dk-ag-lv--outline { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--text-2); }
.dk-ag-week { margin: 0 0 var(--space-3); }
/* (DESIGN 63) a figure and its change, "$4.90K (↑ 38.2%", never split across lines */
.dk-nw { white-space: nowrap; }
.dk-ag-close-line { margin: 0; }
/* (ask 60) the frame says Slack: a title bar naming it over the channel, and Slack's composer at its foot typing requests
   no thread shows, never sent (app.js keeps it as tall as its longest request, so typing never moves the chips); the
   not-a-menu line sits close under the honesty line, in full colour */
.dk-sl-bar { display: flex; align-items: baseline; gap: var(--space-2); padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--line); background: var(--surface-2); font-size: var(--text-xs); }
.dk-sl-app { font-weight: 600; }
.dk-sl-bar-chan { display: none; font-weight: 600; }
.dk-sl-compose { margin: 0 var(--space-4) var(--space-4); padding: var(--space-2) var(--space-3); border-radius: var(--radius-m);
  box-shadow: inset 0 0 0 1px var(--line-strong); font-size: var(--text-s); line-height: 20px; overflow-wrap: anywhere; }
.dk-sl-typed:not(:empty) ~ .dk-sl-ph { display: none; }
.dk-sl-ph { color: var(--text-3); }
/* (6c fix 6) Slack at a glance: a sender's messages in a row share one mark and name (the next one's mark is an empty
   column, closer under it), and on a desk the workspace's channel list beside the channel, this one marked as Slack
   marks it (the accent bar the system draws for the current tab, no literal colour); a picture, so no tab stops */
.dk-sl-msg:has(> .dk-sl-av--cont) { margin-top: calc(-1 * var(--space-2)); }
.dk-sl-av--cont { height: 0; background: none; }
.dk-sl-side { display: none; }
@media (min-width: 900px) {
  .dk-sl-win { display: grid; grid-template-columns: 148px minmax(0, 1fr); }
  .dk-sl-side { display: block; padding: var(--space-3) 0; border-right: 1px solid var(--line); background: var(--surface-2); font-size: var(--text-s); }
  .dk-sl-side-h { margin: 0 0 var(--space-1); padding: 0 var(--space-3); color: var(--text-3); }
  .dk-sl-side ul { list-style: none; margin: 0; padding: 0; }
  .dk-sl-side li { padding: var(--space-1) var(--space-3); color: var(--text-2); line-height: 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dk-sl-side li.is-on { box-shadow: inset 2px 0 0 var(--accent); color: var(--text); font-weight: 600; }
}
.dk-sl-main { min-width: 0; }
/* (6d fix 1) on a phone the frame comes first under its label, so a first-time visitor lands with the frame, its
   caption and Pause in one view: the honesty line and the not-a-menu line follow it, over the example chips they
   describe (the desk keeps them above), and the title bar names the channel as Slack's phone app does, in place of the
   row under it. (6d fix 2) the bar's "Slack" at the body size, as there is no channel list to say it. (DESIGN 63) the one
   line under the label (honesty and not-a-menu in one) follows the frame the same way */
@media (max-width: 899px) {
  .dk-ag-slack { display: flex; flex-direction: column; }
  .dk-ag-slack > .dk-ag-honest, .dk-ag-slack > .dk-ai-chips { order: 1; }
  .dk-ag-slack > .dk-ag-honest { margin-top: var(--space-4); }
  .dk-sl-app { font-size: var(--text-m); }
  .dk-sl-bar-chan { display: inline; font-size: var(--text-s); }
  .dk-sl-ws, .dk-sl-main > .dk-ai-head { display: none; }
}
.dk-msg-acts { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-1) 0 var(--space-2); }
.dk-msg-act { display: inline-flex; align-items: center; height: 28px; padding: 0 var(--space-3); border-radius: var(--radius-s);
  box-shadow: inset 0 0 0 1px var(--line-strong); font-size: var(--text-xs); font-weight: 600; color: var(--text-2);
  cursor: default; user-select: none; }
/* (DESIGN 22) when a new customer pays back: four small figures over the chart (two by two on a phone), the previous
   period's cohorts as the muted line, CAC the dashed one */
.dk-pay-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3) var(--space-4); margin: var(--space-2) 0 var(--space-3); }
@media (min-width: 720px) { .dk-pay-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.dk-pay-stats > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dk-pay-stats b { font-size: var(--text-l); font-weight: 600; }
.dk-pay-prev { fill: none; stroke: var(--chart-muted); stroke-width: 2px; stroke-linejoin: round; }
.dk-pay-table { margin-top: var(--space-3); }
/* (DESIGN 23) the statement: subtotals bold and flush left, the lines that make them one step in, a line's parts two;
   a line that splits further folds open from its name (a 44px target, its chevron turning) */
.dk-bridge .dk-line > td:first-child { padding-left: var(--space-5); }
.dk-bridge .dk-subline > td:first-child { padding-left: calc(var(--space-5) + var(--space-5)); color: var(--text-2); }
.dk-bridge .dk-subline > td { font-size: var(--text-s); }
.dk-bridge .dk-total > td:first-child { font-weight: 600; }
.dk-pl-fold { appearance: none; background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; text-align: left;
  cursor: pointer; min-height: 44px; display: inline-flex; flex-direction: column; justify-content: center; }
.dk-pl-fold::after { content: ""; position: absolute; margin-left: -14px; margin-top: 2px; width: 6px; height: 6px;
  border-right: 1.5px solid var(--text-3); border-bottom: 1.5px solid var(--text-3); transform: rotate(-45deg);
  transition: transform var(--dur) var(--ease); }
.dk-pl-fold[aria-expanded="true"]::after { transform: rotate(45deg); }
.dk-pl-fold:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-s); }
.dk-pl-as { margin: 0 0 var(--space-2); }
.dk-be-stats { margin: 0; }
@media (min-width: 720px) { .dk-be-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* (DESIGN 27) the Share button: the top bar's one icon, at its right (left of the photo card when that is on) */
.dk-sharebtn { flex: none; margin-left: auto; color: var(--text-2); }
/* (ask 62) Hire me in the phone's top bar for every role, a quiet text link like the rail's, left of Share: no side padding
   (its text is a 44 px target already) and half the bar's gap, so the longest title, "Every number checked", keeps its
   whole width at 412 px */
.dk-hire-top { flex: none; display: inline-flex; align-items: center; min-width: var(--tap); min-height: var(--tap); margin-right: calc(-1 * var(--space-1));
  font-size: var(--text-s); color: var(--text-2); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.dk-hire-top + .dk-sharebtn { margin-left: 0; }
@media (hover: hover) { .dk-hire-top:hover { color: var(--text); } }
/* its display above outranks .dk-narrow-only's (same weight, later): the desk has the rail's Hire me, so one, not two */
@media (min-width: 900px) { .dk-hire-top { display: none; } }
/* (6c fix 3) a title too long for a phone's bar beside Hire me and Share shows its short form (the spec page's "short":
   /checked "Checked"), drawn from data-short so the heading's own text, which a screen reader reads, stays whole; the
   same for a tab label the bar would wrap ("tab_short": Profit and loss, "P&L") */
@media (max-width: 419px) {
  .dk-titles > .ds-title[data-short]::before, .ds-tabbar span[data-short]::before { content: attr(data-short) / ""; }
  .dk-titles > .ds-title[data-short] > span, .ds-tabbar span[data-short] > span { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* (DESIGN 33) the consent bar: low and quiet, like a cookie bar; above the phone's tab bar, at the foot of the content
   column on a desk; OK and No thanks one style and one size; never over the welcome or sign-in card (app.js) */
.dk-consent { position: fixed; z-index: 4; left: var(--space-4); right: var(--space-4);
  bottom: calc(56px + var(--space-1) + var(--space-2) + 1px + env(safe-area-inset-bottom) + var(--space-2)); display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2) var(--space-3); padding: var(--space-2) var(--space-3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-m); font-size: var(--text-s); }
.dk-consent[hidden] { display: none; }
.dk-consent-text { margin: 0; flex: 1 1 260px; color: var(--text-2); }
.dk-consent-acts { display: flex; align-items: center; gap: var(--space-2); }
.dk-consent-acts .ds-btn { min-width: 104px; }
.dk-consent-link { display: inline-flex; min-height: var(--tap); align-items: center; padding: 0 var(--space-2); color: var(--accent); }
body.dk-consent-on .ds-main { padding-bottom: calc(var(--space-8) + 96px); }
@media (prefers-reduced-motion: no-preference) {
  .dk-consent { animation: dk-card-in var(--dur) var(--ease) reverse both; animation-direction: normal; }
  .dk-consent.is-leaving { opacity: 0; transition: opacity var(--dur) var(--ease); }
}
@media (min-width: 900px) {
  .dk-consent { bottom: var(--space-4); left: calc(var(--dk-rail-w) + max(var(--space-4), (100vw - var(--dk-rail-w) - var(--content-wide)) / 2 + var(--space-4)));
    right: max(var(--space-4), calc((100vw - var(--dk-rail-w) - var(--content-wide)) / 2 + var(--space-4))); }
}
/* (DESIGN 30) Explore's second metric: the scale switch over its charts, the second series' key, the r line under them */
.dk-x-scale { margin: 0 0 var(--space-2); max-width: 360px; }
.ds-legend > span > i.dk-ix2 { background: var(--chart-2); }
.dk-ix-note { margin: var(--space-2) 0 0; }
.dk-corr { margin: 0 0 var(--space-4); }

/* (a client's P&L, 4 Nov 2026) the statement in $ and % side by side: section heads as small caps rows (no figure), a
   line's benchmark words a column on a desk and under its name on a phone (no sideways scroll), the 2-point flag in
   words beside the name */
.dk-bridge .dk-pl-head > th { font-size: var(--text-xs); letter-spacing: .06em; color: var(--text-2); font-weight: 600;
  text-align: left; padding-top: var(--space-5); }
.dk-bridge .dk-pl-notes { padding-left: var(--space-4); }
.dk-bridge td.dk-pl-notes { font-size: var(--text-s); color: var(--text-2); }   /* its head reads as every other column's */
.dk-bridge .dk-pl-under { display: none; }
.dk-bridge .dk-pl-cap { display: block; font-weight: 400; }
.dk-bridge .dk-pl-flag { margin-left: var(--space-2); white-space: nowrap; }
/* (his words on the page) a line's reason and what a subtotal leaves out, at every width; his notes a desk column, a row
   under the line on a phone; the base's "Baseline" and an n/a line's empty change */
.dk-pl-why, .dk-pl-partial, .dk-bridge .dk-pl-why, .dk-bench .dk-pl-why { display: block; font-weight: 400; white-space: normal; }
.dk-pl-partial { color: var(--text-2); }
.dk-bridge td.dk-pl-eng { font-size: var(--text-xs); color: var(--text-2); min-width: 14em; padding-left: var(--space-4); font-weight: 400; }
.dk-bridge th.dk-pl-eng { padding-left: var(--space-4); }
.dk-bridge .dk-pl-noterow { display: none; }
.dk-pp-empty:empty { display: inline; }
.dk-bench td.dk-bench-note { font-size: var(--text-xs); color: var(--text-2); min-width: 16em; padding-left: var(--space-4); }
.dk-plm-view > button { padding-left: var(--space-3); padding-right: var(--space-3); }
.dk-plm-head { row-gap: var(--space-2); }
.dk-plm .dk-pl-flag { display: block; width: fit-content; margin: var(--space-1) 0 0; font-weight: 400; white-space: normal; }
.dk-plm td[role="rowheader"] .dk-pl-why { max-width: 16em; }
.dk-na-col { margin: var(--space-1) 0 0; }
.dk-tbar-note { margin-top: var(--space-2); }
.dk-na-col:first-of-type { margin-top: var(--space-2); }
.dk-tile-q { display: block; font-weight: 400; text-transform: none; letter-spacing: 0; margin-top: 2px; }
.dk-top .dk-tiles-why { grid-column: 1 / -1; margin: var(--space-1) 0 0; }
/* a sheet that slides sideways keeps each row's name in view (his tracker, the order lines) */
.dk-scroll .dk-grain-table td:first-child, .dk-scroll .dk-grain-table th:first-child,
.dk-hscroll .dk-rows td:first-child, .dk-hscroll .dk-rows th:first-child { position: sticky; left: 0; background: var(--bg); z-index: 1; }
@media (max-width: 599px) {
  .dk-scroll .dk-grain-table td:first-child, .dk-scroll .dk-grain-table th:first-child { left: calc(-1 * var(--space-4)); padding-left: var(--space-4); }
  .dk-bridge .dk-pl-noterow { display: table-row; }
  .dk-bridge tr:has(+ .dk-pl-noterow) > td { border-bottom: 0; }
  .dk-bridge .dk-pl-noterow > td { font-size: var(--text-xs); color: var(--text-2); font-weight: 400; padding-top: 0; white-space: normal; }
  /* four columns on 412 px (Line, $, %, Change in points): the change wraps under its arrow rather than widen the page */
  .dk-bridge[data-as="both"] td .ds-delta { white-space: normal; }
  .dk-bridge .dk-pl-under { display: block; font-weight: 400; }
  .dk-bridge .dk-pl-flag { display: inline-flex; margin: var(--space-1) 0 0; white-space: normal; }
}

/* (a client's P&L) the months side by side: they slide sideways inside the card where they do not fit, the line's name
   stays in view; the benchmark table's bands a column each on a desk and under the metric's name on a phone */
.dk-plm-head { align-items: center; flex-wrap: wrap; }
.dk-plm-head > .dk-caption { margin: 0; }
.dk-plm-scroll { overflow-x: auto; margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4); }
.dk-plm-scroll .dk-plm tbody td:first-child, .dk-plm-scroll .dk-plm thead th:first-child { position: sticky;
  left: calc(-1 * var(--space-4)); background: var(--bg); padding-left: var(--space-4); z-index: 1; }
.dk-plm td[role="rowheader"] { min-width: 10em; }
.dk-plm .dk-line > td:first-child { padding-left: calc(var(--space-4) + var(--space-3)); }
.dk-plm .dk-total > td { font-weight: 600; }
.dk-plm .num { white-space: nowrap; padding-left: var(--space-3); }
.dk-plm .dk-pl-head > th { font-size: var(--text-xs); letter-spacing: .06em; color: var(--text-2); font-weight: 600;
  text-align: left; padding-top: var(--space-5); }
.dk-bench .dk-pl-under { display: none; }
.dk-bench td:last-child, .dk-bench th:last-child { white-space: nowrap; padding-left: var(--space-4); }
.dk-bench td[data-band], .dk-bench th.dk-wide { padding-left: var(--space-4); }
.dk-plm-as > button { min-width: calc(var(--tap) + var(--space-3)); }
@media (max-width: 599px) {
  .dk-bench .dk-pl-under { display: block; font-weight: 400; }
}
