/* Digital Labs — the one place a colour, a face or a size is written down.
 *
 * Taken from the Figma file "Digital Labs", read on 22 September and checked
 * again against the file's styles on 25 September. Three programs read this
 * file: the desk, DLProcessSentinel's window, and later the portal. One
 * definition, because a colour that is #3548FE here and #3447FF there is not a
 * brand, it is two brands that happen to be close.
 *
 * **The rule: a colour and a face are never written as a number outside this
 * file — only as a variable.** `tests/test_the_look_is_one_file.py` keeps it,
 * with a count per file that may only go down: the desk had 246 literal colours
 * on 26 September and a rule that failed on all of them would be a rule nobody
 * could commit, so it ratchets instead.
 *
 * This replaces the Carbon palette the desk was built with. Carbon's most
 * recognisable trait is square corners everywhere, and `static/desk.css` says in
 * as many words that rounding them undoes the look in one commit — which was
 * true and is now beside the point, because the look is deliberately changing to
 * this one. Pills and 16/24 radii below are the design system, not a drift.
 */

:root {
  /* --- colour ------------------------------------------------------------
   * Named as the Figma file names them, so that a conversation about a colour
   * and a line of CSS use the same word. The comment is the role, which is the
   * part that decides whether a new use is right.
   */
  --dl-black-primary: #181818;      /* text; dark plates */
  --dl-black-secondary: #262626;

  --dl-blue-primary: #3548FE;       /* the accent: button, the logo's dot,
                                     * active states, progress */
  --dl-blue-dark: #2535CC;          /* hover, and the pressed state */
  --dl-blue-secondary: #E2E4F8;     /* a light backing for the accent */
  --dl-blue-tertiary: #EBEDFF;      /* a card singled out */
  --dl-blue-light: #CFD2F9;
  /* From the Figma file's styles, read on 22 September (claude/design-tokens.md,
   * in the advisor's notes): the accent's hover and pressed state, and the
   * second light accent. The same numbers as dark and light; named as the file
   * names them. */
  --dl-blue-quarternary: #2535CC;
  --dl-blue-quarternary-light: #CFD2F9;

  --dl-grey-primary: #4D4D4D;       /* secondary text */
  --dl-grey-secondary: #787878;     /* captions; navigation not on this page */
  --dl-grey-tertiary: #A6A6A6;      /* placeholders */
  --dl-grey-bg: #F5F5F7;            /* the ground a card or a section sits on */
  --dl-grey-border: #DFDFDF;        /* dividers and frames */

  --dl-white-primary: #FFFFFF;      /* the page */

  --dl-green-primary: #3BCFA0;      /* it passed: QA green, a gate closed */
  --dl-red-primary: #F43152;        /* it did not: a gate open, a refusal */

  /* **There is no amber in the Figma file**, and the concept card needs one: a
   * reading that is good but not ten is neither a pass nor a failure, and
   * colouring it green or red would be a lie in one direction or the other.
   * Until 26 September it was the text colour, as a named placeholder. Bulat's
   * decision that day: a standard amber, temporary — amber 700, chosen because
   * it is read as *text* here (a tag, a warning line) and not only as a fill.
   * Measured: 5.02:1 on the page white, 4.61:1 on the grey ground, and as the
   * tags draw it (80 % with black) 5.62:1 on the blue backing; beside the accent
   * #3548FE it differs in hue, not in lightness. Numbers in
   * reports/2026-09-26-the-desk-and-the-instrument.md.
   * not from the design file; replace when Figma gets one */
  --dl-amber-primary: #B45309;

  /* --- the face ----------------------------------------------------------
   * Neue Haas Grotesk Display Pro, in three weights: 45 Light, 55 Roman, 65
   * Medium. **There is no web licence for it yet**, so the stack below is the
   * fallback chain with the nearest metrics — Helvetica Neue first because it is
   * the face Neue Haas was drawn from, then Inter, then Arial. Nothing here
   * references a font file: a page that pointed at a file it does not have would
   * ask for it on every load and fall back anyway. The `@font-face` blocks below
   * the root ask **only for a face installed on the machine** (`local()`), by the
   * weight each style is — so a machine with the face draws it, and every other
   * one falls through the stack as before. A test keeps that honest.
   */
  --dl-face: "Neue Haas Grotesk Display Pro", "Helvetica Neue", Inter, Arial,
             sans-serif;
  /* For numbers that have to line up in a column — a queue, a log, a hash.
   * Not part of the Figma file; named here because the alternative is each page
   * choosing its own. */
  --dl-mono: "Cascadia Mono", Consolas, ui-monospace, monospace;
  /* The names the desk's sheets and screens already read. */
  --sans: var(--dl-face);

  --dl-light: 300;                  /* 45 Light */
  --dl-roman: 400;                  /* 55 Roman */
  --dl-medium: 500;                 /* 65 Medium */

  /* --- the scale, desktop ------------------------------------------------
   * Name, size, line height, weight — exactly as the file gives them. A size
   * without its line height is half a decision, so they are always a pair.
   */
  --dl-h1: var(--dl-light) 56px/64px var(--dl-face);
  --dl-h2: var(--dl-light) 48px/56px var(--dl-face);

  --dl-t1: var(--dl-light) 44px/52px var(--dl-face);
  --dl-t2: var(--dl-medium) 40px/48px var(--dl-face);
  --dl-t3: var(--dl-medium) 32px/40px var(--dl-face);
  --dl-t4: var(--dl-light) 28px/36px var(--dl-face);
  --dl-t5: var(--dl-medium) 20px/28px var(--dl-face);
  --dl-t6: var(--dl-medium) 18px/24px var(--dl-face);
  --dl-t7: var(--dl-light) 20px/28px var(--dl-face);

  --dl-b1: var(--dl-medium) 16px/24px var(--dl-face);
  --dl-b2: var(--dl-roman) 16px/24px var(--dl-face);
  --dl-b3: var(--dl-roman) 14px/20px var(--dl-face);

  --dl-l1: var(--dl-medium) 16px/24px var(--dl-face);
  --dl-l2: var(--dl-roman) 16px/24px var(--dl-face);
  --dl-l3: var(--dl-medium) 14px/20px var(--dl-face);
  --dl-l4: var(--dl-roman) 14px/20px var(--dl-face);
  --dl-l5: var(--dl-roman) 12px/20px var(--dl-face);
  --dl-l6: var(--dl-medium) 10px/16px var(--dl-face);

  /* A shadow and a scrim. The design file gives neither, and both were in the
   * desk as `rgba(22,22,22,.14)` and `rgba(15,19,25,.45)` — two different blacks
   * nobody chose. Derived from the palette's own black instead, so a shade is
   * still the brand's: `color-mix` towards `transparent` is how you get alpha out
   * of a named colour without writing a fourth number. If the file ever gives a
   * real elevation scale these become it. */
  --dl-shadow: 0 2px 8px color-mix(in srgb, var(--dl-black-primary) 14%,
                                   transparent);
  --dl-scrim: color-mix(in srgb, var(--dl-black-primary) 45%, transparent);

  /* --- shape -------------------------------------------------------------- */
  --dl-radius-small: 16px;          /* a small card */
  --dl-radius-large: 24px;          /* a large one */
  --dl-radius-pill: 999px;          /* the header, and a primary button */
  --dl-radius-field: 8px;           /* a field a person types into */
  --dl-hairline: 1px;               /* a divider, in grey/border */

  /* A control somebody has to hit with a thumb. Apple's figure and everybody
   * else's since: below this, a button on a phone is a button that gets missed,
   * and `tests/test_a_press_is_not_a_decision.py` measures it. */
  --dl-touch: 44px;

  /* --- what the desk calls these ----------------------------------------
   * The roles, so that a page says what a thing *is* rather than which token it
   * happens to use. Changing what a page looks like should be a change here,
   * not in eight templates.
   */
  --dl-page-title: var(--dl-t3);
  --dl-card-title: var(--dl-t6);
  --dl-body: var(--dl-b2);
  --dl-caption: var(--dl-l4);
  --dl-meta: var(--dl-l5);
  --dl-badge: var(--dl-l6);
  --dl-badge-tracking: 0.08em;      /* badges are uppercase, and uppercase
                                     * without tracking is a wall */

  /* --- the colour roles, and the dark theme (21 October, (25) and (28)) ---
   * What a page colours *by*: each role has two values, the light one from the
   * palette above and a dark one below. A page carries data-theme="light" or
   * "dark"; without it, the system's prefers-color-scheme decides. The table
   * is the advisor's, approved by Bulat on 21 October (design-tokens.md, its
   * dark-theme section); tests/test_the_dark_theme_is_a_second_value_of_each_role.py
   * holds this file to it. A page written on the palette is not themed until it
   * asks for roles — and only such a page says `color-scheme`, by its own
   * <meta name="color-scheme" content="light dark">: put here, the system's
   * dark would turn every older page's fields dark on its white ground. */
  --dl-bg-page: var(--dl-white-primary);
  --dl-bg-card: var(--dl-grey-bg);            /* in the dark, with a border */
  --dl-bg-card-selected: var(--dl-blue-tertiary);
  --dl-bg-accent-soft: var(--dl-blue-secondary);
  --dl-bg-accent-soft-2: var(--dl-blue-light);
  --dl-border: var(--dl-grey-border);
  --dl-text-primary: var(--dl-black-primary);
  --dl-text-secondary: var(--dl-grey-primary);
  --dl-text-tertiary: var(--dl-grey-secondary);
  --dl-text-placeholder: var(--dl-grey-tertiary);
  --dl-accent-fill: var(--dl-blue-primary);
  --dl-accent-fill-hover: var(--dl-blue-quarternary);
  --dl-accent-text: var(--dl-blue-primary);
  --dl-on-accent: var(--dl-white-primary);
  --dl-success: var(--dl-green-primary);
  --dl-error: var(--dl-red-primary);
  /* The palette's text amber in the light, the table's in the dark (Bulat, 24
   * October, option b): #E0A030 on white is 2.27:1 and a role is read as text sooner
   * or later. */
  --dl-warn: var(--dl-amber-primary);
  --dl-inverse-bg: var(--dl-black-primary);   /* the DL square, «Check now» */
  --dl-inverse-text: var(--dl-white-primary);
  --dl-role-shadow: 0 8px 24px color-mix(in srgb, var(--dl-black-primary) 8%, transparent);
}

/* The dark values, by the page's word… */
:root[data-theme="dark"] {
  color-scheme: dark;
  --dl-bg-page: #121214;
  --dl-bg-card: #1C1C1F;
  --dl-bg-card-selected: #1E2340;
  --dl-bg-accent-soft: #232A55;
  --dl-bg-accent-soft-2: #2B3470;
  --dl-border: #2E2E33;
  --dl-text-primary: #F2F2F2;
  --dl-text-secondary: #C2C2C6;
  --dl-text-tertiary: #8E8E94;
  --dl-text-placeholder: #5E5E66;
  --dl-accent-fill: #3548FE;
  --dl-accent-fill-hover: #4A5BFF;           /* lighter in the dark, not darker */
  --dl-accent-text: #8A96FF;
  --dl-on-accent: #FFFFFF;
  --dl-success: #4ADBAC;
  --dl-error: #FF5C78;
  --dl-warn: #E0A030;
  --dl-inverse-bg: #F2F2F2;
  --dl-inverse-text: #181818;
  --dl-role-shadow: none;                     /* a border in its place */
}

/* …and by the system's, when the page says nothing. The same values: CSS has
 * no way to name one block from two selectors across a media query. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --dl-bg-page: #121214;
    --dl-bg-card: #1C1C1F;
    --dl-bg-card-selected: #1E2340;
    --dl-bg-accent-soft: #232A55;
    --dl-bg-accent-soft-2: #2B3470;
    --dl-border: #2E2E33;
    --dl-text-primary: #F2F2F2;
    --dl-text-secondary: #C2C2C6;
    --dl-text-tertiary: #8E8E94;
    --dl-text-placeholder: #5E5E66;
    --dl-accent-fill: #3548FE;
    --dl-accent-fill-hover: #4A5BFF;
    --dl-accent-text: #8A96FF;
    --dl-on-accent: #FFFFFF;
    --dl-success: #4ADBAC;
    --dl-error: #FF5C78;
    --dl-warn: #E0A030;
    --dl-inverse-bg: #F2F2F2;
    --dl-inverse-text: #181818;
    --dl-role-shadow: none;
  }
}

/* The scale on a phone. Not smaller versions of the same numbers: the file gives
 * its own, and three of them are not simply reduced — mobile t3 is 24/32 against
 * desktop's 32/40, mobile t7 is 16/24 against desktop's 20/28 Light, and mobile
 * has a t8 that the desktop scale has no equivalent for. Written out rather than
 * derived, because a rule that produced these from the desktop set would be a
 * rule with three exceptions. */
@media (max-width: 600px) {
  :root {
    --dl-h1: var(--dl-light) 40px/48px var(--dl-face);
    --dl-h2: var(--dl-light) 32px/40px var(--dl-face);

    --dl-t1: var(--dl-light) 36px/40px var(--dl-face);
    --dl-t2: var(--dl-medium) 32px/40px var(--dl-face);
    --dl-t3: var(--dl-medium) 24px/32px var(--dl-face);
    --dl-t4: var(--dl-light) 28px/36px var(--dl-face);
    --dl-t5: var(--dl-medium) 20px/28px var(--dl-face);
    --dl-t6: var(--dl-medium) 18px/24px var(--dl-face);
    --dl-t7: var(--dl-medium) 16px/24px var(--dl-face);
    --dl-t8: var(--dl-light) 20px/24px var(--dl-face);

    /* body is the same on both, which is the point of a body size */

    --dl-l1: var(--dl-medium) 16px/24px var(--dl-face);
    --dl-l2: var(--dl-roman) 16px/24px var(--dl-face);
    --dl-l3: var(--dl-medium) 20px/28px var(--dl-face);
    --dl-l4: var(--dl-roman) 14px/20px var(--dl-face);
    --dl-l5: var(--dl-roman) 12px/20px var(--dl-face);
    --dl-l6: var(--dl-medium) 14px/20px var(--dl-face);
  }
}

/* --- the components the file draws ---------------------------------------
 *
 * Four of them, and they are here rather than in a page's own stylesheet
 * because all three programs show them. A component in two files is two
 * components that look alike until one is edited.
 */

/* The floating pill header. `DL` reversed out of a black rounded square, a bold
 * blue dot, then GENESIS in Medium. */
.dl-mast {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  border-radius: var(--dl-radius-pill);
  background: var(--dl-white-primary);
  border: var(--dl-hairline) solid var(--dl-grey-border);
  color: var(--dl-black-primary);
}

.dl-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font: var(--dl-t6);
  color: var(--dl-black-primary);
  text-decoration: none;
  white-space: nowrap;
}

.dl-logo-mark {
  display: inline-grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.5rem;
  background: var(--dl-black-primary);
  color: var(--dl-white-primary);
  font: var(--dl-l3);
  letter-spacing: 0.02em;
}

/* The dot between DL and GENESIS. A character rather than a drawn circle, so it
 * sits on the same baseline as the words whatever the face turns out to be. */
.dl-logo-dot {
  color: var(--dl-blue-primary);
  font-weight: 700;
}

.dl-logo-word { font-weight: var(--dl-medium); }

/* The component after the word — Factory, Ziggurat, Portal, Watchdog (17
 * October): which of the four this screen is. */
.dl-logo-app { color: var(--dl-grey-primary); font-weight: var(--dl-roman); }

/* The face, when the machine has it. **Only `local()`**: there is no web
 * licence, so nothing is served; the names are the ones the three installed
 * styles answer to, and the weights are the ones `--dl-light/roman/medium` ask
 * for. A machine without the face skips these and takes the next in the stack. */
@font-face {
  font-family: "Neue Haas Grotesk Display Pro";
  font-weight: 300;
  src: local("Neue Haas Grotesk Display Pro 45 Light"),
       local("NeueHaasGroteskDisplayPro-45Light"), local("NHaasGroteskDSPro-45Lt");
}

@font-face {
  font-family: "Neue Haas Grotesk Display Pro";
  font-weight: 400;
  src: local("Neue Haas Grotesk Display Pro 55 Roman"),
       local("NeueHaasGroteskDisplayPro-55Roman"), local("NHaasGroteskDSPro-55Rg");
}

@font-face {
  font-family: "Neue Haas Grotesk Display Pro";
  font-weight: 500;
  src: local("Neue Haas Grotesk Display Pro 65 Medium"),
       local("NeueHaasGroteskDisplayPro-65Medium"), local("NHaasGroteskDSPro-65Md");
}

/* --- the controls (29 September) -------------------------------------------
 * One button for every page, the design file's: a primary is a blue pill with
 * white words; a secondary is an outlined pill of the same height — a
 * grey/border frame, black words, grey/bg on hover (30 September: underlined
 * words read as a link, not a button; underlining stays with a link inside a
 * sentence, like «Enrich them»); a danger is red
 * words and fills red only when it is armed for the second press (`data-arm`,
 * static/arm.js) — the fill is the "are you sure". `.btn-sm` is the same
 * shape, smaller. The older names the pages use are aliases, so no template
 * changes: `.p`/`.btn-primary`/`.dl-button` primary, a bare `.btn` and
 * `.btn-secondary/-tertiary/-ghost/.quiet` secondary, `.d`/`.btn-danger`
 * danger. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.25rem;
  padding: 0 1.25rem;
  border: var(--dl-hairline) solid var(--dl-grey-border);
  border-radius: var(--dl-radius-pill);
  background: var(--dl-white-primary);
  color: var(--dl-black-primary);
  font: var(--dl-l4);
  text-decoration: none;
  cursor: pointer;
}

.btn:hover:not(:disabled) { background: var(--dl-grey-bg); }

.btn.p, .btn-primary, .dl-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 1.25rem;
  border: 0;
  border-radius: var(--dl-radius-pill);
  background: var(--dl-blue-primary);
  color: var(--dl-white-primary);
  font: var(--dl-l3);
  text-decoration: none;
  cursor: pointer;
}

.btn.p:hover:not(:disabled), .btn-primary:hover:not(:disabled),
.dl-button:hover, .dl-button:focus-visible {
  background: var(--dl-blue-quarternary);
  color: var(--dl-white-primary);
}

.btn.d, .btn-danger {
  padding: 0 1rem;
  border: var(--dl-hairline) solid var(--dl-red-primary);
  background: transparent;
  color: var(--dl-red-primary);
  text-decoration: none;
}

.btn.d:hover:not(:disabled), .btn-danger:hover:not(:disabled) {
  color: var(--dl-red-primary);
}

/* Armed: whatever it was, it is now the thing that cannot be undone. */
.btn[data-armed], .dl-button[data-armed] {
  border: var(--dl-hairline) solid var(--dl-red-primary);
  background: var(--dl-red-primary);
  color: var(--dl-white-primary);
  text-decoration: none;
}

.btn-sm { min-height: 1.75rem; font: var(--dl-l5); }
.btn-sm, .btn.p.btn-sm, .btn-primary.btn-sm, .btn.d.btn-sm { padding: 0 0.85rem; }

.btn:disabled, .dl-button[disabled] {
  background: var(--dl-grey-border);
  color: var(--dl-grey-secondary);
  border-color: var(--dl-grey-border);
  cursor: not-allowed;
}

.btn:not(.p):not(.btn-primary):not(.d):not(.btn-danger):disabled {
  background: transparent;
}

.btn:focus-visible, .dl-button:focus-visible {
  outline: 2px solid var(--dl-blue-primary);
  outline-offset: 2px;
}

/* --- hover and focus, one rule for every control (block (26)) -----
 * Not every button showed a hover: «Send an invitation» and «Erase their
 * data» changed colour, «Do not contact» did not — a danger button kept its
 * red words on hover, and the many buttons that are not `.btn` (the queue's,
 * the console's, the portal's tabs) had whatever their page gave them. One
 * halo on hover for every control on the desk and in the cabinet, under every
 * rule that says more: `:where` gives it no weight, so a page's own hover
 * still wins, and only a control nobody styled is drawn by this alone. A
 * halo, not a fill, so an armed button (`data-arm`, red) keeps its red. Focus
 * from the keyboard is the blue ring, the same for all. */
:where(button, [role="button"], a.btn, a.qbtn, input[type="submit"],
       input[type="button"], summary, select):where(:hover):where(:not(:disabled)) {
  box-shadow: 0 0 0 3px var(--dl-blue-quarternary-light);
}
:where(a, button, [role="button"], input, select, textarea, summary,
       [tabindex]):where(:focus-visible) {
  outline: 2px solid var(--dl-blue-primary);
  outline-offset: 2px;
}
.btn.d:hover:not(:disabled), .btn-danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--dl-red-primary) 8%, var(--dl-white-primary));
}
/* Armed stays armed under the pointer. */
.btn[data-armed]:hover:not(:disabled), .dl-button[data-armed]:hover {
  background: var(--dl-red-primary);
  color: var(--dl-white-primary);
}

/* A thumb on a phone. */
@media (max-width: 600px) {
  .btn, .dl-button { min-height: var(--dl-touch); }
}

/* Copying a line (static/copy.js). Here and not in desk.css because every page
 * loads this file and Review does not load desk.css: there the icon was an
 * unstyled button and fell into a row of its own in the line's grid. Small, at
 * the right of its own line, out of the flow (29 September). */
.ln, .hrow, .qrow, .srow { position: relative; }
.cp {
  position: absolute; right: 0.25rem; top: 50%; transform: translateY(-50%);
  display: none;
  width: 1.1rem; height: 1.1rem; min-height: 0; min-width: 0; padding: 0;
  font-size: 0.7rem; line-height: 1;
  color: inherit; background: transparent;
  border: 0; border-radius: var(--dl-radius-pill);
  opacity: 0.7; cursor: copy;
}
.cp:hover, .cp:focus { opacity: 1; }
.ln:hover > .cp, .hrow:hover > .cp, .qrow:hover > .cp, .srow:hover > .cp,
.cp:focus { display: inline-flex; align-items: center; justify-content: center; }
.cp.done { color: var(--dl-green-primary); opacity: 1; }
.copy-all {
  margin-left: 0.75rem;
  padding: 0 0.5rem;
  font: var(--dl-l5);
  color: inherit; background: transparent;
  border: var(--dl-hairline) solid currentColor; border-radius: var(--dl-radius-pill);
  opacity: 0.8; cursor: copy;
}
.copy-all.done { color: var(--dl-green-primary); opacity: 1; }
/* On a phone there is no hover: every line carries its icon. */
@media (hover: none) {
  .ln > .cp, .hrow > .cp, .qrow > .cp, .srow > .cp {
    display: inline-flex; align-items: center; justify-content: center;
  }
}

/* A card. Two radii, because the file uses the larger one for the things a page
 * is built out of and the smaller for the things inside them. */
.dl-card {
  background: var(--dl-grey-bg);
  border-radius: var(--dl-radius-small);
  padding: 1rem;
}

.dl-card-large { border-radius: var(--dl-radius-large); padding: 1.5rem; }

/* Singled out — the one card a page is about. */
.dl-card-chosen { background: var(--dl-blue-tertiary); }

/* An eyebrow: a small dot and a word above a heading, saying what kind of thing
 * this is. */
.dl-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font: var(--dl-badge);
  letter-spacing: var(--dl-badge-tracking);
  text-transform: uppercase;
  color: var(--dl-grey-secondary);
}

.dl-eyebrow::before {
  content: "";
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--dl-blue-primary);
}

.dl-rule {
  border: 0;
  border-top: var(--dl-hairline) solid var(--dl-grey-border);
  margin: 1rem 0;
}

/* What a reading came out as. Three colours and a fourth state that is not a
 * colour: "it did not pass" is not a shade of red, it is the absence of a
 * score, and `core/qa.py` is where that distinction is decided. */
.dl-ok { color: var(--dl-green-primary); }
.dl-warn { color: var(--dl-amber-primary); }
.dl-bad { color: var(--dl-red-primary); }
