/* Fettlex styles - generated by Tailwind from src/input.css.
   Edit src/input.css, then run `npm run build:css` (readable) or
   `npm run build:css:min` (minified, for production). Do not edit the
   generated static/tailwind.css by hand. */

*, ::before, ::after {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

::backdrop {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

/* ! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com */

/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/

*,
::before,
::after {
  box-sizing: border-box;
  /* 1 */
  border-width: 0;
  /* 2 */
  border-style: solid;
  /* 2 */
  border-color: var(--edge);
  /* 2 */
}

::before,
::after {
  --tw-content: '';
}

/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/

html,
:host {
  line-height: 1.5;
  /* 1 */
  -webkit-text-size-adjust: 100%;
  /* 2 */
  -moz-tab-size: 4;
  /* 3 */
  -o-tab-size: 4;
     tab-size: 4;
  /* 3 */
  font-family: 'Atkinson Hyperlegible Next', ui-sans-serif, system-ui, Segoe UI, Roboto, Arial;
  /* 4 */
  font-feature-settings: normal;
  /* 5 */
  font-variation-settings: normal;
  /* 6 */
  -webkit-tap-highlight-color: transparent;
  /* 7 */
}

/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/

body {
  margin: 0;
  /* 1 */
  line-height: inherit;
  /* 2 */
}

/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/

hr {
  height: 0;
  /* 1 */
  color: inherit;
  /* 2 */
  border-top-width: 1px;
  /* 3 */
}

/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/

abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
          text-decoration: underline dotted;
}

/*
Remove the default font size and weight for headings.
*/

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}

/*
Reset links to optimize for opt-in styling instead of opt-out.
*/

a {
  color: inherit;
  text-decoration: inherit;
}

/*
Add the correct font weight in Edge and Safari.
*/

b,
strong {
  font-weight: bolder;
}

/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/

code,
kbd,
samp,
pre {
  font-family: 'Atkinson Hyperlegible Mono', ui-monospace, Consolas, Menlo, monospace;
  /* 1 */
  font-feature-settings: normal;
  /* 2 */
  font-variation-settings: normal;
  /* 3 */
  font-size: 1em;
  /* 4 */
}

/*
Add the correct font size in all browsers.
*/

small {
  font-size: 80%;
}

/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/

table {
  text-indent: 0;
  /* 1 */
  border-color: inherit;
  /* 2 */
  border-collapse: collapse;
  /* 3 */
}

/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/

button,
input,
optgroup,
select,
textarea {
  font-family: inherit;
  /* 1 */
  font-feature-settings: inherit;
  /* 1 */
  font-variation-settings: inherit;
  /* 1 */
  font-size: 100%;
  /* 1 */
  font-weight: inherit;
  /* 1 */
  line-height: inherit;
  /* 1 */
  letter-spacing: inherit;
  /* 1 */
  color: inherit;
  /* 1 */
  margin: 0;
  /* 2 */
  padding: 0;
  /* 3 */
}

/*
Remove the inheritance of text transform in Edge and Firefox.
*/

button,
select {
  text-transform: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
  -webkit-appearance: button;
  /* 1 */
  background-color: transparent;
  /* 2 */
  background-image: none;
  /* 2 */
}

/*
Use the modern Firefox focus style for all focusable elements.
*/

:-moz-focusring {
  outline: auto;
}

/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/

:-moz-ui-invalid {
  box-shadow: none;
}

/*
Add the correct vertical alignment in Chrome and Firefox.
*/

progress {
  vertical-align: baseline;
}

/*
Correct the cursor style of increment and decrement buttons in Safari.
*/

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/

[type='search'] {
  -webkit-appearance: textfield;
  /* 1 */
  outline-offset: -2px;
  /* 2 */
}

/*
Remove the inner padding in Chrome and Safari on macOS.
*/

::-webkit-search-decoration {
  -webkit-appearance: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/

::-webkit-file-upload-button {
  -webkit-appearance: button;
  /* 1 */
  font: inherit;
  /* 2 */
}

/*
Add the correct display in Chrome and Safari.
*/

summary {
  display: list-item;
}

/*
Removes the default spacing and border for appropriate elements.
*/

blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
  margin: 0;
}

fieldset {
  margin: 0;
  padding: 0;
}

legend {
  padding: 0;
}

ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
Reset default styling for dialogs.
*/

dialog {
  padding: 0;
}

/*
Prevent resizing textareas horizontally by default.
*/

textarea {
  resize: vertical;
}

/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder, textarea::-moz-placeholder {
  opacity: 1;
  /* 1 */
  color: #9ca3af;
  /* 2 */
}

input::placeholder,
textarea::placeholder {
  opacity: 1;
  /* 1 */
  color: #9ca3af;
  /* 2 */
}

/*
Set the default cursor for buttons.
*/

button,
[role="button"] {
  cursor: pointer;
}

/*
Make sure disabled buttons don't get the pointer cursor.
*/

:disabled {
  cursor: default;
}

/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
   This can trigger a poorly considered lint error in some tools but is included by design.
*/

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
  display: block;
  /* 1 */
  vertical-align: middle;
  /* 2 */
}

/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/

img,
video {
  max-width: 100%;
  height: auto;
}

/* Make elements with the HTML hidden attribute stay hidden by default */

[hidden]:where(:not([hidden="until-found"])) {
  display: none;
}

button {
  transition: transform var(--dur-fast) var(--ease-out);
}

/* Tailwind's preflight greys every placeholder #9ca3af: 2.4:1 on our fields.
     The theme's subtle text clears 4.5:1 in both themes (test_contrast_tokens). */

input::-moz-placeholder, textarea::-moz-placeholder {
  color: var(--fg-subtle);
  opacity: 1;
}

input::placeholder, textarea::placeholder {
  color: var(--fg-subtle);
  opacity: 1;
}

.container {
  width: 100%;
}

@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }
}

@media (min-width: 1024px) {
  .container {
    max-width: 1024px;
  }
}

@media (min-width: 1280px) {
  .container {
    max-width: 1280px;
  }
}

@media (min-width: 1536px) {
  .container {
    max-width: 1536px;
  }
}

.\!btn {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 0.4rem !important;
  border-radius: var(--r-control) !important;
  border: var(--bw) solid transparent !important;
  padding: 0.5rem 0.9rem !important;
  font-size: 0.9375rem !important;
  line-height: 1.25rem !important;
  font-weight: 600 !important;
  text-align: center !important;
  cursor: pointer !important;
  transition: transform var(--dur-fast) var(--ease-out),
                background-color 150ms ease, border-color 150ms ease, color 150ms ease !important;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border-radius: var(--r-control);
  border: var(--bw) solid transparent;
  padding: 0.5rem 0.9rem;
  font-size: 0.9375rem;
  line-height: 1.25rem;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out),
                background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}

.\!btn:active:not(:disabled) {
  transform: scale(.97) !important;
}

.btn:active:not(:disabled) {
  transform: scale(.97);
}

.\!btn:disabled {
  cursor: not-allowed !important;
  background: var(--line) !important;
  border-color: var(--line) !important;
  color: var(--fg-subtle) !important;
}

.btn:disabled {
  cursor: not-allowed;
  background: var(--line);
  border-color: var(--line);
  color: var(--fg-subtle);
}

/* Busy is not unavailable: a sign-in button disabled while it submits
     (authform.js sets aria-busy) keeps its colour and shows its spinner. */

.btn-primary[aria-busy="true"]:disabled {
  background: var(--accent-fill);
  border-color: transparent;
  color: #fff;
  cursor: progress;
}

.btn-sm {
  padding: 0.375rem 0.7rem;
  font-size: 0.875rem;
}

.btn-lg {
  padding: 0.75rem 1.25rem;
}

.btn-primary {
  background: var(--accent-fill);
  color: #fff;
}

.btn-secondary {
  background: var(--card);
  border-color: var(--edge);
  color: var(--fg);
}

.btn-ghost {
  background: transparent;
  color: var(--fg-muted);
}

.btn-danger {
  background: var(--danger-fill);
  color: #fff;
}

.btn-info {
  background: var(--info-fill);
  color: #fff;
}

.btn-danger-outline {
  background: transparent;
  border-color: var(--edge);
  color: var(--danger);
}

@media (hover: hover) {
  .btn-primary:hover:not(:disabled) {
    background: var(--accent-fill-hover);
  }

  .btn-secondary:hover:not(:disabled) {
    border-color: var(--accent);
  }

  .btn-ghost:hover:not(:disabled), .btn-icon:hover:not(:disabled) {
    background: var(--inset);
    color: var(--fg);
  }

  .btn-danger:hover:not(:disabled) {
    background: var(--danger-fill-hover);
  }

  .btn-info:hover:not(:disabled) {
    background: var(--info-fill-hover);
  }

  .btn-danger-outline:hover:not(:disabled) {
    background: var(--danger-bg);
    border-color: var(--danger-border);
  }
}

.\!input {
  width: 100% !important;
  border-radius: var(--r-control) !important;
  border: var(--bw) solid var(--edge) !important;
  background: var(--inset) !important;
  color: var(--fg) !important;
  padding: 0.5rem 0.75rem !important;
  font-size: 0.9375rem !important;
  line-height: 1.375rem !important;
  transition: border-color 150ms ease, box-shadow 150ms ease !important;
}

.input, .select {
  width: 100%;
  border-radius: var(--r-control);
  border: var(--bw) solid var(--edge);
  background: var(--inset);
  color: var(--fg);
  padding: 0.5rem 0.75rem;
  font-size: 0.9375rem;
  line-height: 1.375rem;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.\!input::-moz-placeholder {
  color: var(--fg-subtle) !important;
  opacity: 1 !important;
}

.\!input::placeholder {
  color: var(--fg-subtle) !important;
  opacity: 1 !important;
}

.input::-moz-placeholder {
  color: var(--fg-subtle);
  opacity: 1;
}

.input::placeholder {
  color: var(--fg-subtle);
  opacity: 1;
}

/* The ring itself is the global :focus-visible outline; the border joins in. */

.\!input:focus {
  border-color: var(--accent) !important;
}

.input:focus, .select:focus {
  border-color: var(--accent);
}

.\!chip {
  display: inline-flex !important;
  align-items: center !important;
  gap: 0.3rem !important;
  border-radius: 999px !important;
  border: var(--bw) solid var(--edge) !important;
  padding: 0.2rem 0.65rem !important;
  font-size: 0.875rem !important;
  color: var(--fg-muted) !important;
  background: transparent !important;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease !important;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border-radius: 999px;
  border: var(--bw) solid var(--edge);
  padding: 0.2rem 0.65rem;
  font-size: 0.875rem;
  color: var(--fg-muted);
  background: transparent;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}

.\!chip[aria-pressed="true"], .\!chip.is-on {
  border-color: var(--accent) !important;
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
  font-weight: 600 !important;
}

.chip[aria-pressed="true"], .chip.is-on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.\!chip[aria-pressed="true"], .\!chip.is-on {
  border-color: var(--accent) !important;
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
  font-weight: 600 !important;
}

.\!card {
  background: var(--card) !important;
  border: var(--bw) solid var(--edge-soft) !important;
  border-radius: var(--r-box) !important;
}

.card {
  background: var(--card);
  border: var(--bw) solid var(--edge-soft);
  border-radius: var(--r-box);
}

/* One enter for every overlay: fade and rise from .96, 200ms ease-out. No
     exit animation -- closing is often from the keyboard (Esc), and a closing
     dialog that lingers is in the way of the work underneath. */

.dialog-backdrop {
  background: rgba(8, 9, 11, .55);
}

.dialog {
  background: var(--panel);
  border: var(--bw) solid var(--edge);
  border-radius: var(--r-box);
  box-shadow: var(--shadow-pop);
}

@media (prefers-reduced-motion: no-preference) {
  .dialog-backdrop {
    animation: wiq-fade-in var(--dur) var(--ease-out);
  }

  .dialog {
    animation: wiq-dialog-in var(--dur) var(--ease-out);
  }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

.pointer-events-none {
  pointer-events: none;
}

.visible {
  visibility: visible;
}

.invisible {
  visibility: hidden;
}

.collapse {
  visibility: collapse;
}

.static {
  position: static;
}

.fixed {
  position: fixed;
}

.absolute {
  position: absolute;
}

.relative {
  position: relative;
}

.sticky {
  position: sticky;
}

.inset-0 {
  inset: 0px;
}

.bottom-28 {
  bottom: 7rem;
}

.left-2\.5 {
  left: 0.625rem;
}

.right-1\.5 {
  right: 0.375rem;
}

.right-5 {
  right: 1.25rem;
}

.top-0 {
  top: 0px;
}

.top-1\/2 {
  top: 50%;
}

.top-10 {
  top: 2.5rem;
}

.z-10 {
  z-index: 10;
}

.z-30 {
  z-index: 30;
}

.z-50 {
  z-index: 50;
}

.z-\[60\] {
  z-index: 60;
}

.z-\[70\] {
  z-index: 70;
}

.z-\[80\] {
  z-index: 80;
}

.-m-1 {
  margin: -0.25rem;
}

.mx-0\.5 {
  margin-left: 0.125rem;
  margin-right: 0.125rem;
}

.mx-4 {
  margin-left: 1rem;
  margin-right: 1rem;
}

.mx-auto {
  margin-left: auto;
  margin-right: auto;
}

.-ml-1 {
  margin-left: -0.25rem;
}

.-mr-1 {
  margin-right: -0.25rem;
}

.-mt-0\.5 {
  margin-top: -0.125rem;
}

.mb-1 {
  margin-bottom: 0.25rem;
}

.mb-2 {
  margin-bottom: 0.5rem;
}

.mb-3 {
  margin-bottom: 0.75rem;
}

.mb-4 {
  margin-bottom: 1rem;
}

.mb-5 {
  margin-bottom: 1.25rem;
}

.mb-6 {
  margin-bottom: 1.5rem;
}

.mb-8 {
  margin-bottom: 2rem;
}

.ml-0\.5 {
  margin-left: 0.125rem;
}

.ml-auto {
  margin-left: auto;
}

.mt-0\.5 {
  margin-top: 0.125rem;
}

.mt-1 {
  margin-top: 0.25rem;
}

.mt-1\.5 {
  margin-top: 0.375rem;
}

.mt-2 {
  margin-top: 0.5rem;
}

.mt-2\.5 {
  margin-top: 0.625rem;
}

.mt-3 {
  margin-top: 0.75rem;
}

.mt-3\.5 {
  margin-top: 0.875rem;
}

.mt-4 {
  margin-top: 1rem;
}

.mt-5 {
  margin-top: 1.25rem;
}

.mt-6 {
  margin-top: 1.5rem;
}

.mt-8 {
  margin-top: 2rem;
}

.mt-auto {
  margin-top: auto;
}

.line-clamp-2 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.block {
  display: block;
}

.inline-block {
  display: inline-block;
}

.inline {
  display: inline;
}

.flex {
  display: flex;
}

.inline-flex {
  display: inline-flex;
}

.table {
  display: table;
}

.grid {
  display: grid;
}

.contents {
  display: contents;
}

.hidden {
  display: none;
}

.h-1 {
  height: 0.25rem;
}

.h-1\.5 {
  height: 0.375rem;
}

.h-10 {
  height: 2.5rem;
}

.h-14 {
  height: 3.5rem;
}

.h-2 {
  height: 0.5rem;
}

.h-2\.5 {
  height: 0.625rem;
}

.h-3 {
  height: 0.75rem;
}

.h-3\.5 {
  height: 0.875rem;
}

.h-4 {
  height: 1rem;
}

.h-5 {
  height: 1.25rem;
}

.h-6 {
  height: 1.5rem;
}

.h-7 {
  height: 1.75rem;
}

.h-8 {
  height: 2rem;
}

.h-9 {
  height: 2.25rem;
}

.h-full {
  height: 100%;
}

.max-h-40 {
  max-height: 10rem;
}

.max-h-\[88vh\] {
  max-height: 88vh;
}

.max-h-\[90vh\] {
  max-height: 90vh;
}

.min-h-0 {
  min-height: 0px;
}

.min-h-11 {
  min-height: 2.75rem;
}

.min-h-\[36px\] {
  min-height: 36px;
}

.min-h-\[44px\] {
  min-height: 44px;
}

.w-1\.5 {
  width: 0.375rem;
}

.w-1\/3 {
  width: 33.333333%;
}

.w-10 {
  width: 2.5rem;
}

.w-14 {
  width: 3.5rem;
}

.w-16 {
  width: 4rem;
}

.w-2\.5 {
  width: 0.625rem;
}

.w-2\/3 {
  width: 66.666667%;
}

.w-20 {
  width: 5rem;
}

.w-24 {
  width: 6rem;
}

.w-3 {
  width: 0.75rem;
}

.w-3\.5 {
  width: 0.875rem;
}

.w-3\/4 {
  width: 75%;
}

.w-32 {
  width: 8rem;
}

.w-36 {
  width: 9rem;
}

.w-4 {
  width: 1rem;
}

.w-40 {
  width: 10rem;
}

.w-5 {
  width: 1.25rem;
}

.w-6 {
  width: 1.5rem;
}

.w-64 {
  width: 16rem;
}

.w-7 {
  width: 1.75rem;
}

.w-8 {
  width: 2rem;
}

.w-80 {
  width: 20rem;
}

.w-9 {
  width: 2.25rem;
}

.w-full {
  width: 100%;
}

.w-px {
  width: 1px;
}

.min-w-0 {
  min-width: 0px;
}

.min-w-\[44px\] {
  min-width: 44px;
}

.max-w-2xl {
  max-width: 42rem;
}

.max-w-3xl {
  max-width: 48rem;
}

.max-w-4xl {
  max-width: 56rem;
}

.max-w-6xl {
  max-width: 72rem;
}

.max-w-\[110px\] {
  max-width: 110px;
}

.max-w-\[80\%\] {
  max-width: 80%;
}

.max-w-\[85\%\] {
  max-width: 85%;
}

.max-w-\[95px\] {
  max-width: 95px;
}

.max-w-full {
  max-width: 100%;
}

.max-w-md {
  max-width: 28rem;
}

.max-w-sm {
  max-width: 24rem;
}

.max-w-xl {
  max-width: 36rem;
}

.flex-1 {
  flex: 1 1 0%;
}

.shrink {
  flex-shrink: 1;
}

.shrink-0 {
  flex-shrink: 0;
}

.grow {
  flex-grow: 1;
}

.basis-0 {
  flex-basis: 0px;
}

.basis-1\/2 {
  flex-basis: 50%;
}

.-translate-y-1\/2 {
  --tw-translate-y: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.transform {
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

@keyframes pulse {
  50% {
    opacity: .5;
  }
}

.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.animate-spin {
  animation: spin 1s linear infinite;
}

.cursor-not-allowed {
  cursor: not-allowed;
}

.cursor-pointer {
  cursor: pointer;
}

.select-all {
  -webkit-user-select: all;
     -moz-user-select: all;
          user-select: all;
}

.resize-none {
  resize: none;
}

.resize {
  resize: both;
}

.list-decimal {
  list-style-type: decimal;
}

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

.grid-cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.flex-col {
  flex-direction: column;
}

.flex-wrap {
  flex-wrap: wrap;
}

.place-items-center {
  place-items: center;
}

.items-start {
  align-items: flex-start;
}

.items-end {
  align-items: flex-end;
}

.items-center {
  align-items: center;
}

.items-baseline {
  align-items: baseline;
}

.justify-start {
  justify-content: flex-start;
}

.justify-end {
  justify-content: flex-end;
}

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

.justify-between {
  justify-content: space-between;
}

.gap-0\.5 {
  gap: 0.125rem;
}

.gap-1 {
  gap: 0.25rem;
}

.gap-1\.5 {
  gap: 0.375rem;
}

.gap-2 {
  gap: 0.5rem;
}

.gap-2\.5 {
  gap: 0.625rem;
}

.gap-3 {
  gap: 0.75rem;
}

.gap-4 {
  gap: 1rem;
}

.gap-6 {
  gap: 1.5rem;
}

.gap-x-2\.5 {
  -moz-column-gap: 0.625rem;
       column-gap: 0.625rem;
}

.gap-x-3 {
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
}

.gap-x-6 {
  -moz-column-gap: 1.5rem;
       column-gap: 1.5rem;
}

.gap-y-1\.5 {
  row-gap: 0.375rem;
}

.gap-y-2\.5 {
  row-gap: 0.625rem;
}

.space-y-0\.5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));
}

.space-y-1 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
}

.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
}

.space-y-2 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
}

.space-y-3 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
}

.space-y-4 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
}

.space-y-6 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
}

.divide-y > :not([hidden]) ~ :not([hidden]) {
  --tw-divide-y-reverse: 0;
  border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
  border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
}

.divide-line-soft > :not([hidden]) ~ :not([hidden]) {
  border-color: var(--edge-soft);
}

.self-stretch {
  align-self: stretch;
}

.overflow-hidden {
  overflow: hidden;
}

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

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

.overscroll-contain {
  overscroll-behavior: contain;
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.whitespace-nowrap {
  white-space: nowrap;
}

.whitespace-pre-line {
  white-space: pre-line;
}

.whitespace-pre-wrap {
  white-space: pre-wrap;
}

.break-all {
  word-break: break-all;
}

.rounded {
  border-radius: var(--r-control);
}

.rounded-2xl {
  border-radius: var(--r-box);
}

.rounded-full {
  border-radius: 9999px;
}

.rounded-lg {
  border-radius: var(--r-control);
}

.rounded-md {
  border-radius: var(--r-control);
}

.rounded-xl {
  border-radius: var(--r-box);
}

.rounded-bl-sm {
  border-bottom-left-radius: 0.125rem;
}

.rounded-br-sm {
  border-bottom-right-radius: 0.125rem;
}

.border {
  border-width: 1px;
}

.border-2 {
  border-width: 2px;
}

.border-b {
  border-bottom-width: 1px;
}

.border-l-2 {
  border-left-width: 2px;
}

.border-r {
  border-right-width: 1px;
}

.border-t {
  border-top-width: 1px;
}

.border-t-2 {
  border-top-width: 2px;
}

.border-dashed {
  border-style: dashed;
}

.border-brand {
  border-color: var(--accent);
}

.border-danger {
  border-color: var(--danger);
}

.border-danger-border {
  border-color: var(--danger-border);
}

.border-info {
  border-color: var(--info);
}

.border-info-border {
  border-color: var(--info-border);
}

.border-line {
  border-color: var(--edge);
}

.border-line-soft {
  border-color: var(--edge-soft);
}

.border-success-border {
  border-color: var(--success-border);
}

.border-transparent {
  border-color: transparent;
}

.border-warn-border {
  border-color: var(--warn-border);
}

.border-white\/25 {
  border-color: rgb(255 255 255 / 0.25);
}

.border-white\/40 {
  border-color: rgb(255 255 255 / 0.4);
}

.border-t-white {
  --tw-border-opacity: 1;
  border-top-color: rgb(255 255 255 / var(--tw-border-opacity, 1));
}

.bg-black\/40 {
  background-color: rgb(0 0 0 / 0.4);
}

.bg-brand-fill {
  background-color: var(--accent-fill);
}

.bg-brand-soft {
  background-color: var(--accent-soft);
}

.bg-canvas {
  background-color: var(--canvas);
}

.bg-card {
  background-color: var(--card);
}

.bg-danger-bg {
  background-color: var(--danger-bg);
}

.bg-danger-fill {
  background-color: var(--danger-fill);
}

.bg-fg-subtle {
  background-color: var(--fg-subtle);
}

.bg-header {
  background-color: var(--header);
}

.bg-info-bg {
  background-color: var(--info-bg);
}

.bg-inset {
  background-color: var(--inset);
}

.bg-line {
  background-color: var(--line);
}

.bg-line-soft {
  background-color: var(--line-soft);
}

.bg-panel {
  background-color: var(--panel);
}

.bg-success-bg {
  background-color: var(--success-bg);
}

.bg-transparent {
  background-color: transparent;
}

.bg-warn-bg {
  background-color: var(--warn-bg);
}

.bg-warn-fill {
  background-color: var(--warn-fill);
}

.object-contain {
  -o-object-fit: contain;
     object-fit: contain;
}

.p-0\.5 {
  padding: 0.125rem;
}

.p-1 {
  padding: 0.25rem;
}

.p-1\.5 {
  padding: 0.375rem;
}

.p-2 {
  padding: 0.5rem;
}

.p-2\.5 {
  padding: 0.625rem;
}

.p-3 {
  padding: 0.75rem;
}

.p-3\.5 {
  padding: 0.875rem;
}

.p-4 {
  padding: 1rem;
}

.p-5 {
  padding: 1.25rem;
}

.p-6 {
  padding: 1.5rem;
}

.px-1 {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}

.px-1\.5 {
  padding-left: 0.375rem;
  padding-right: 0.375rem;
}

.px-2 {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.px-2\.5 {
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}

.px-3 {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

.px-3\.5 {
  padding-left: 0.875rem;
  padding-right: 0.875rem;
}

.px-4 {
  padding-left: 1rem;
  padding-right: 1rem;
}

.px-5 {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.px-6 {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

.py-0\.5 {
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
}

.py-1 {
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}

.py-1\.5 {
  padding-top: 0.375rem;
  padding-bottom: 0.375rem;
}

.py-10 {
  padding-top: 2.5rem;
  padding-bottom: 2.5rem;
}

.py-2 {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}

.py-2\.5 {
  padding-top: 0.625rem;
  padding-bottom: 0.625rem;
}

.py-3 {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}

.py-4 {
  padding-top: 1rem;
  padding-bottom: 1rem;
}

.py-6 {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}

.py-8 {
  padding-top: 2rem;
  padding-bottom: 2rem;
}

.pb-1 {
  padding-bottom: 0.25rem;
}

.pb-1\.5 {
  padding-bottom: 0.375rem;
}

.pb-2 {
  padding-bottom: 0.5rem;
}

.pb-3 {
  padding-bottom: 0.75rem;
}

.pl-2 {
  padding-left: 0.5rem;
}

.pl-3 {
  padding-left: 0.75rem;
}

.pl-5 {
  padding-left: 1.25rem;
}

.pl-8 {
  padding-left: 2rem;
}

.pr-2 {
  padding-right: 0.5rem;
}

.pr-3 {
  padding-right: 0.75rem;
}

.pr-7 {
  padding-right: 1.75rem;
}

.pt-1 {
  padding-top: 0.25rem;
}

.pt-2 {
  padding-top: 0.5rem;
}

.pt-2\.5 {
  padding-top: 0.625rem;
}

.pt-3 {
  padding-top: 0.75rem;
}

.pt-3\.5 {
  padding-top: 0.875rem;
}

.pt-4 {
  padding-top: 1rem;
}

.pt-5 {
  padding-top: 1.25rem;
}

.pt-6 {
  padding-top: 1.5rem;
}

.text-left {
  text-align: left;
}

.text-center {
  text-align: center;
}

.text-right {
  text-align: right;
}

.align-super {
  vertical-align: super;
}

.font-mono {
  font-family: 'Atkinson Hyperlegible Mono', ui-monospace, Consolas, Menlo, monospace;
}

.font-sans {
  font-family: 'Atkinson Hyperlegible Next', ui-sans-serif, system-ui, Segoe UI, Roboto, Arial;
}

.text-2xl {
  font-size: 1.5rem;
  line-height: 2rem;
}

.text-2xs {
  font-size: 0.875rem;
  line-height: 1.25rem;
}

.text-3xl {
  font-size: 1.875rem;
  line-height: 2.25rem;
}

.text-4xl {
  font-size: 2.25rem;
  line-height: 2.5rem;
}

.text-base {
  font-size: 1rem;
  line-height: 1.5rem;
}

.text-lg {
  font-size: 1.125rem;
  line-height: 1.75rem;
}

.text-sm {
  font-size: 0.9375rem;
  line-height: 1.375rem;
}

.text-xl {
  font-size: 1.25rem;
  line-height: 1.75rem;
}

.text-xs {
  font-size: 0.875rem;
  line-height: 1.25rem;
}

.font-bold {
  font-weight: 700;
}

.font-medium {
  font-weight: 500;
}

.font-normal {
  font-weight: 400;
}

.font-semibold {
  font-weight: 600;
}

.uppercase {
  text-transform: uppercase;
}

.lowercase {
  text-transform: lowercase;
}

.capitalize {
  text-transform: capitalize;
}

.italic {
  font-style: italic;
}

.tabular-nums {
  --tw-numeric-spacing: tabular-nums;
  font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
}

.leading-none {
  line-height: 1;
}

.leading-relaxed {
  line-height: 1.625;
}

.leading-snug {
  line-height: 1.375;
}

.leading-tight {
  line-height: 1.25;
}

.tracking-\[0\.3em\] {
  letter-spacing: 0.3em;
}

.tracking-tight {
  letter-spacing: -0.025em;
}

.tracking-wide {
  letter-spacing: 0.025em;
}

.tracking-widest {
  letter-spacing: 0.1em;
}

.text-brand {
  color: var(--accent);
}

.text-danger {
  color: var(--danger);
}

.text-fg {
  color: var(--fg);
}

.text-fg-muted {
  color: var(--fg-muted);
}

.text-fg-subtle {
  color: var(--fg-subtle);
}

.text-header-muted {
  --tw-text-opacity: 1;
  color: rgb(198 205 214 / var(--tw-text-opacity, 1));
}

.text-info {
  color: var(--info);
}

.text-success {
  color: var(--success);
}

.text-warn {
  color: var(--warn-fg);
}

.text-white {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

.underline {
  text-decoration-line: underline;
}

.decoration-dotted {
  text-decoration-style: dotted;
}

.antialiased {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.accent-brand-fill {
  accent-color: var(--accent-fill);
}

.accent-danger-fill {
  accent-color: var(--danger-fill);
}

.accent-info-fill {
  accent-color: var(--info-fill);
}

.opacity-100 {
  opacity: 1;
}

.opacity-60 {
  opacity: 0.6;
}

.shadow-lg {
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-md {
  --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-sm {
  --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.outline-none {
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.filter {
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.transition {
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.transition-\[width\] {
  transition-property: width;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.transition-transform {
  transition-property: transform;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.duration-150 {
  transition-duration: 150ms;
}

.duration-200 {
  transition-duration: 200ms;
}

.ease-linear {
  transition-timing-function: linear;
}

.h-dvh-screen {
  height: 100vh;
  height: 100dvh;
}

.min-h-dvh-screen {
  min-height: 100vh;
  min-height: 100dvh;
}

.\[overflow-wrap\:anywhere\] {
  overflow-wrap: anywhere;
}

/* Self-hosted Atkinson Hyperlegible Next + Mono (Braille Institute; SIL Open
   Font License, static/fonts/OFL-Atkinson-Hyperlegible.txt). Drawn so 1/l/I and
   0/O never collide -- what part numbers and fault codes need on a workshop
   screen. One variable woff2 per style and script covers weights 200-800;
   unicode-range means the latin-ext file only loads for a name that needs it.
   No CDN: the CSP is default-src 'self', and the app must work offline. */

@font-face {
  font-family: 'Atkinson Hyperlegible Next';

  font-style: normal;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonNext-latin.woff2') format('woff2');

  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Atkinson Hyperlegible Next';

  font-style: normal;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonNext-latin-ext.woff2') format('woff2');

  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Atkinson Hyperlegible Next';

  font-style: italic;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonNext-Italic-latin.woff2') format('woff2');

  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Atkinson Hyperlegible Next';

  font-style: italic;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonNext-Italic-latin-ext.woff2') format('woff2');

  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Atkinson Hyperlegible Mono';

  font-style: normal;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonMono-latin.woff2') format('woff2');

  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Atkinson Hyperlegible Mono';

  font-style: normal;

  font-weight: 200 800;

  font-display: swap;

  src: url('/static/fonts/AtkinsonMono-latin-ext.woff2') format('woff2');

  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ----------------------------------------------------------------------- */

/* Theme tokens. Light is the default (:root); .dark on <html> swaps them.  */

/* The semantic color utilities in tailwind.config.js read these vars, so   */

/* one class (e.g. bg-card) renders correctly in both modes.               */

/* ----------------------------------------------------------------------- */

/* LOOK C, "BUILT FOR THE BENCH" -- picked 2026-10-02 from three looks shown on
   the real app. Higher-contrast neutrals than before, one red, and every text
   colour readable at the sizes it is used at: tests/test_contrast_tokens.py
   measures each pair below in both themes, so a value that drifts under WCAG
   AA fails the build rather than a technician's eyes in a bright workshop.

   ACCENT IS TWO COLOURS. --accent is red TEXT (links, icons, outlines) and
   --accent-fill is a red BACKGROUND with white words on it. In dark mode they
   cannot be the same red: text needs a light red to read on near-black, and a
   white label needs a deep red behind it. One shared value failed one or the
   other (white on the light red measured 2.4:1). */

:root {
  color-scheme: light;
  --canvas: #e7e9ec;
  --panel: #f6f7f8;
  --card: #ffffff;
  --inset: #fbfbfc;
  --line: #c9ced5;
  --line-soft: #e1e4e8;
  /* OUTLINES, apart from the fills above -- see borderColor in tailwind.config.js.
     Asked for 2026-09-29: "darker, slightly bolder outlines to everything in
     light mode to help with clarity". 2px, because 1.5px is drawn as 1px on a
     standard screen (measured in Chrome at devicePixelRatio 1). */
  --edge: #6c7581;
  --edge-soft: #9aa2ad;
  --bw: 2px;
  --fg: #0f1216;
  --fg-muted: #343c47;
  --fg-subtle: #4a5360;
  --accent: #a3221b;
  --accent-strong: #7f1a14;
  /* hover on red text */
  --accent-fill: #b3261e;
  --accent-fill-hover: #911d17;
  --accent-soft: #fde3df;
  /* a red tint behind red text or an icon */
  --accent-ring: rgba(179, 38, 30, .28);
  --flash: #fde3df;
  /* citation jump highlight */
  --header: #0f1216;
  /* the top bar is dark in both themes */
  /* STATUS. Each has text (readable on the page and on its own -bg), a tint,
     an outline, and where something is pressed or filled, a -fill. */
  --danger: #b42318;
  --danger-bg: #fdecea;
  --danger-border: #d9827a;
  --danger-fill: #b42318;
  --danger-fill-hover: #8f1c13;
  --warn-fg: #8a3c00;
  --warn-bg: #fff4e0;
  --warn-border: #c27a12;
  --warn-fill: #c27a12;
  --info: #0b5c8a;
  --info-bg: #e3f0f8;
  --info-border: #5f9cc4;
  --info-fill: #0b6aa2;
  --info-fill-hover: #08527d;
  --success: #166534;
  --success-bg: #e6f4ea;
  --success-border: #5ea97a;
  --logo-1: #b3261e;
}

.dark {
  color-scheme: dark;
  --canvas: #0b0d10;
  --panel: #121519;
  --card: #191d22;
  --inset: #0f1215;
  --line: #2c323a;
  --line-soft: #20252b;
  --edge: #646e7b;
  --edge-soft: #444c57;
  --bw: 1px;
  --fg: #f3f5f7;
  --fg-muted: #c6cdd6;
  --fg-subtle: #a2abb7;
  --accent: #ff8076;
  --accent-strong: #ffaaa3;
  --accent-fill: #c42b22;
  --accent-fill-hover: #a8231c;
  --accent-soft: #2c1714;
  --accent-ring: rgba(255, 128, 118, .32);
  --flash: #2c1714;
  --header: #08090b;
  --danger: #ff8a80;
  --danger-bg: #2c1714;
  --danger-border: #8a3a33;
  --danger-fill: #c42b22;
  --danger-fill-hover: #a8231c;
  --warn-fg: #fcd9a8;
  --warn-bg: #2a1c0e;
  --warn-border: #8a5a1f;
  --warn-fill: #d98a0b;
  --info: #8ccaf2;
  --info-bg: #0d2232;
  --info-border: #2f6a8f;
  --info-fill: #1673ad;
  --info-fill-hover: #125d8c;
  --success: #7ee2a8;
  --success-bg: #0e2a1b;
  --success-border: #2f7a50;
  --logo-1: #ff6b60;
}

/* ---- Shape and motion ----------------------------------------------------
   Firm corners: 4px on anything pressed or typed into, 6px on a box that
   holds things. Motion is Emil Kowalski's strong ease-out -- quick to
   answer the hand, quiet to settle. */

:root {
  --r-control: 4px;
  --r-box: 6px;
  --ring-w: 3px;
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --ease-drawer: cubic-bezier(.32, .72, 0, 1);
  /* iOS-like sheet curve */
  --dur-fast: 120ms;
  --dur: 200ms;
  --shadow-pop: 0 8px 24px rgba(15, 18, 22, .18);
  --font-mono: 'Atkinson Hyperlegible Mono', ui-monospace, Consolas, Menlo, monospace;
}

.dark {
  --shadow-pop: 0 8px 24px rgba(0, 0, 0, .5);
}

/* Every Tailwind box outline (`border`) takes the width token: 2px in light
   mode, 1px in dark. Divider lines (border-t / border-b) stay 1px -- doubled,
   the page reads as a grid of heavy rules rather than clearer boxes. */

.border {
  border-width: var(--bw);
}

body {
  transition: background-color .25s ease, color .25s ease;
}

/* App chrome - scrollbar + animations read theme tokens. */

/* Smooth scrolling only for people who have not asked their system for less
   motion; for them a jump is the honest version of a scroll. */

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--fg-subtle);
}

@keyframes flash {
  0% {
    background: var(--flash);
  }

  100% {
    background: transparent;
  }
}

.flash {
  animation: flash 1.2s ease-out;
}

/* Colour only: a chip is hovered tens of times an answer, and a lift on
   something that small reads as jitter, not feedback. */

.cite-chip {
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

/* Mono only where a technician reads a code or a page number. */

.cite-chip, #viewer-page-count, #viewer-page-input {
  font-family: var(--font-mono);
}

/* ----------------------------------------------------------------------- */

/* Answer body (.wiq-answer) - clean, scannable layout for the bench.       */

/* Tailwind's base reset strips list/heading styling, so it is all defined  */

/* explicitly here for the Markdown the renderer emits.                     */

/* ----------------------------------------------------------------------- */

.wiq-answer {
  font-size: 0.95rem;
  line-height: 1.7;
  color: var(--fg);
}

.wiq-answer > :first-child {
  margin-top: 0;
}

.wiq-answer > :last-child {
  margin-bottom: 0;
}

.wiq-answer p {
  margin: 0.6rem 0;
}

.wiq-answer strong {
  font-weight: 700;
  color: var(--fg);
}

.wiq-answer em {
  font-style: italic;
}

.wiq-answer code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: var(--inset);
  border: var(--bw) solid var(--edge-soft);
  padding: 0.05rem 0.3rem;
  border-radius: var(--r-control);
}

.wiq-answer h2, .wiq-answer h3, .wiq-answer h4 {
  font-weight: 700;
  color: var(--fg);
  line-height: 1.3;
  margin: 1rem 0 0.4rem;
}

.wiq-answer h2 {
  font-size: 1.1rem;
}

.wiq-answer h3 {
  font-size: 1rem;
}

.wiq-answer h4 {
  font-size: 0.95rem;
}

/* Pipe tables (parts lists / spec tables). Scroll horizontally on small
   screens rather than overflow the page. */

.wiq-answer .wiq-table-wrap {
  overflow-x: auto;
  margin: 0.8rem 0;
}

.wiq-answer table.wiq-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.9rem;
  line-height: 1.45;
}

.wiq-answer .wiq-table th, .wiq-answer .wiq-table td {
  border: var(--bw) solid var(--edge);
  padding: 0.4rem 0.6rem;
  text-align: left;
  vertical-align: top;
}

.wiq-answer .wiq-table thead th {
  background: var(--inset);
  font-weight: 700;
}

.wiq-answer .wiq-table tbody tr:nth-child(even) td {
  background: var(--inset);
}

.wiq-answer .wiq-table code {
  white-space: nowrap;
}

/* Numbered steps - accent badges so a tech can track position at a glance. */

.wiq-answer ol.wiq-steps {
  list-style: none;
  counter-reset: wiq-step;
  margin: 0.7rem 0;
  padding: 0;
}

.wiq-answer ol.wiq-steps > li {
  counter-increment: wiq-step;
  position: relative;
  padding: 0.15rem 0 0.15rem 2.4rem;
  margin: 0.55rem 0;
  min-height: 1.65rem;
}

.wiq-answer ol.wiq-steps > li::before {
  content: counter(wiq-step);
  position: absolute;
  left: 0;
  top: 0.05rem;
  width: 1.65rem;
  height: 1.65rem;
  background: var(--accent-fill);
  color: #fff;
  border-radius: 9999px;
  display: grid;
  place-items: center;
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1;
}

/* Bulleted points - accent dot markers. */

.wiq-answer ul.wiq-list {
  list-style: none;
  margin: 0.6rem 0;
  padding: 0;
}

.wiq-answer ul.wiq-list > li {
  position: relative;
  padding: 0.1rem 0 0.1rem 1.4rem;
  margin: 0.35rem 0;
}

.wiq-answer ul.wiq-list > li::before {
  content: "";
  position: absolute;
  left: 0.35rem;
  top: 0.72rem;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 9999px;
  background: var(--accent);
}

.wiq-answer ul.wiq-list ul.wiq-list {
  margin: 0.3rem 0 0;
}

/* Safety / note callouts. */

.wiq-answer .callout {
  display: flex;
  gap: 0.55rem;
  align-items: flex-start;
  margin: 0.6rem 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid;
  border-radius: var(--r-control);
  font-size: 0.9rem;
  line-height: 1.55;
}

.wiq-answer .callout-ico {
  flex-shrink: 0;
  font-size: 1rem;
  line-height: 1.45;
}

.wiq-answer .callout-body {
  min-width: 0;
}

.wiq-answer .callout-warn {
  background: var(--warn-bg);
  border-color: var(--warn-border);
  color: var(--warn-fg);
}

.wiq-answer .callout-warn strong {
  color: var(--warn-fg);
}

.wiq-answer .callout-note {
  background: var(--inset);
  border-color: var(--edge-soft);
  color: var(--fg-muted);
}

/* ---- Source viewer (full-screen overlay) ---- */

@media (prefers-reduced-motion: no-preference) {
  #viewer {
    animation: viewer-in var(--dur) var(--ease-out);
  }
}

/* Keep the page/zoom controls from squishing so they stay tappable. */

#viewer-page-controls > * {
  flex-shrink: 0;
}

/* Hide the native number-input spinners on the page field: the prev/next
   buttons already step pages, and the spinner overlays (and clips) the last
   digit of 3-4 digit page numbers. */

#viewer-page-input::-webkit-inner-spin-button,
#viewer-page-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

#viewer-page-input {
  -moz-appearance: textfield;
  -webkit-appearance: textfield;
          appearance: textfield;
}

/* Desktop is the safe default: one row, close button top-right (base markup
   classes only). Below the sm breakpoint (640px) the header wraps so the
   page/zoom controls drop to their own centred second row while the library
   toggle, title and close stay on the top row — close never leaves the corner.
   Living in a media query (not sm:-prefixed markup) means a stale cached CSS
   can never collapse the desktop layout into the mobile one. */

@media (max-width: 639.98px) {
  #viewer > div:first-child {
    flex-wrap: wrap;
  }

  #viewer-page-controls {
    order: 99;
    width: 100%;
    margin-left: 0;
    justify-content: center;
  }
}

@keyframes viewer-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* ⚠️ A BOOK FOR SEVERAL TRACTORS SAYS SO -- see coverageNote in localcatalog.js.
   BOTH layouts, so it lives here and not in the new-layout section, where every
   rule must be scoped away from classic (test_layout_features.py). The warning
   colours are the ones already defined for light and dark. */

.cover-note {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.3rem;
  padding: 0.15rem 0.5rem;
  border-radius: var(--r-control);
  border: var(--bw) solid var(--warn-border);
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  white-space: normal;
}

.cover-note svg {
  width: 0.9rem;
  height: 0.9rem;
  flex: none;
}

.cover-note-info {
  border-color: var(--edge);
  background: var(--inset);
  color: var(--fg-muted);
  font-weight: 500;
}

/* ---- Toasts (static/js/toast.js) ---- */

#wiq-toasts {
  position: fixed;
  z-index: 60;
  /* above the settings/viewer modals */
  right: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: .5rem;
  width: min(92vw, 22rem);
  pointer-events: none;
  /* let clicks through the empty stack area */
}

.wiq-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  padding: .625rem .75rem;
  border-radius: var(--r-box);
  border: var(--bw) solid var(--edge);
  background: var(--card);
  color: var(--fg);
  box-shadow: var(--shadow-pop);
  font-size: .875rem;
  line-height: 1.4;
  animation: wiq-toast-in var(--dur) var(--ease-out);
}

.wiq-toast-out {
  animation: wiq-toast-out 150ms var(--ease-out) forwards;
}

.wiq-toast-icon {
  flex: none;
  margin-top: 1px;
}

.wiq-toast-msg {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.wiq-toast-x {
  flex: none;
  font-size: 1rem;
  line-height: 1;
  color: var(--fg-subtle);
  padding: 0 .125rem;
}

.wiq-toast-x:hover {
  color: var(--fg);
}

.wiq-toast-success .wiq-toast-icon {
  color: var(--success);
}

.wiq-toast-error   .wiq-toast-icon {
  color: var(--danger);
}

.wiq-toast-error   {
  border-color: var(--danger-border);
}

.wiq-toast-info    .wiq-toast-icon {
  color: var(--accent);
}

@keyframes wiq-toast-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes wiq-toast-out {
  to {
    opacity: 0;
    transform: translateY(10px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .wiq-toast {
    animation: none;
  }

  .wiq-toast-out {
    animation: none;
    opacity: 0;
  }
}

/* ---- Keyboard focus ring (Stage 7 a11y) ----
   Visible only for keyboard users (:focus-visible), so mouse clicks stay clean.
   Covers icon buttons, links, the role="button" source/doc cards, and controls. */

button:focus-visible,
a:focus-visible,
select:focus-visible,
input:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: var(--ring-w) solid var(--accent);
  outline-offset: 2px;
}

#question:focus-visible {
  outline: none;
}

/* ---- Skeleton loaders ---- */

.wiq-skel {
  background: linear-gradient(90deg, var(--inset) 0%, var(--line-soft) 50%, var(--inset) 100%);
  background-size: 200% 100%;
  animation: wiq-shimmer 1.3s ease-in-out infinite;
}

@keyframes wiq-shimmer {
  from {
    background-position: 200% 0;
  }

  to {
    background-position: -200% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wiq-skel {
    animation: none;
    background: var(--line-soft);
  }
}

/* ---- "Sources & proof" reveal ---- */

/* display:none can't transition, so animate a short fade+slide on open. Close
   stays instant. */

.sources-body:not(.hidden) {
  animation: wiq-fade-slide .18s ease-out;
}

@keyframes wiq-fade-slide {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sources-body:not(.hidden) {
    animation: none;
  }
}

/* ---- Search-scope indicator ---- */

#scope-bar.scope-empty {
  color: var(--accent);
}

/* ---- Streaming answer caret (Stage 8) ---- */

/* A blinking caret trails the text while the answer streams in; removed when the
   final cited answer swaps in. */

.wiq-answer.wiq-streaming::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  vertical-align: -0.15em;
  background: var(--accent);
  animation: wiq-caret 1s step-end infinite;
}

@keyframes wiq-caret {
  50% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wiq-answer.wiq-streaming::after {
    animation: none;
  }
}

/* PDF.js draws each page here; centre it with breathing room. */

#viewer-canvas {
  display: block;
  margin: 1rem auto;
  box-shadow: 0 1px 8px rgba(0,0,0,.18);
}

#viewer-text {
  max-width: 48rem;
  margin: 0 auto;
  padding: 1.5rem;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--fg);
  /* A <pre>, so the browser would set it in the code font. It is a manual's
     own prose, read for minutes at a time -- the reading face, not mono. */
  font-family: inherit;
}

/* App sidebar: static column on desktop, off-canvas drawer on mobile. */

@media (prefers-reduced-motion: no-preference) {
  #sidebar {
    transition: transform 240ms var(--ease-drawer);
  }
}

@media (max-width: 767px) {
  #sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 40;
    transform: translateX(-100%);
    /* Fixed drawer covers the full viewport: keep its content clear of the
       notch / home indicator (inert where env() is 0 or unsupported). */
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left);
  }

  #sidebar.sidebar-open {
    transform: translateX(0);
    box-shadow: 4px 0 16px rgba(0,0,0,.28);
  }
}

/* Viewer library: static column on desktop, off-canvas drawer on mobile. */

@media (prefers-reduced-motion: no-preference) {
  #viewer-library-panel {
    transition: transform 240ms var(--ease-drawer);
  }
}

@media (max-width: 767px) {
  #viewer-library-panel {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    transform: translateX(-100%);
  }

  #viewer-library-panel.viewer-lib-open {
    transform: translateX(0);
    box-shadow: 4px 0 16px rgba(0,0,0,.28);
  }
}

/* ----------------------------------------------------------------------- */

/* Mobile / iOS / installed-PWA polish.                                      */

/* ----------------------------------------------------------------------- */

/* Full-height that tracks iOS Safari's dynamic toolbar. 100vh overflows
   under the collapsed toolbar; 100dvh fixes it where supported (iOS 15.4+),
   with 100vh kept as the fallback for older engines. */

/* iOS Safari auto-zooms the page when a focused input's font-size is under
   16px. Force >=16px on touch devices only, so the desktop stays compact. */

@media (hover: none) and (pointer: coarse) {
  input, select, textarea {
    font-size: 16px;
  }

  /* 44px minimum touch targets (Apple HIG) for the icon-only controls.
     min-* beats the w-9/h-9 utilities without changing the desktop look. */

  #nav-toggle, #theme-toggle, #visual-btn, #mic-btn, #send-btn,
  #viewer-lib-toggle, #viewer-close, #viewer-download,
  #viewer-page-prev, #viewer-page-next, #viewer-zoom-out, #viewer-zoom-in {
    min-width: 2.75rem;
    min-height: 2.75rem;
    display: grid;
    place-items: center;
  }
}

/* Notch / home-indicator safe areas (viewport-fit=cover in the <meta>).
   env() resolves to 0 in normal browser tabs, so these are inert outside
   installed/standalone mode. Browsers without env() drop the declaration
   and keep the original utility padding. */

body {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

#app-header {
  padding-top: env(safe-area-inset-top);
}

#composer {
  padding-bottom: calc(0.75rem + env(safe-area-inset-bottom));
}

#viewer > div:first-child {
  padding-top: calc(0.5rem + env(safe-area-inset-top));
}

#viewer-content {
  padding-bottom: env(safe-area-inset-bottom);
}

#settings-modal {
  padding: max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right))
           max(1rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
}

/* Stop iOS rubber-band scroll from chaining out of the app's scroll panes
   into the (non-scrolling) page, and keep momentum scrolling on older iOS. */

#messages, #viewer-content, #doc-list, #conv-list, #viewer-library {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* Settings modal: left-hand section nav. */

.settings-nav {
  width: 100%;
  text-align: left;
  padding: 0.375rem 0.75rem;
  margin-bottom: 0.125rem;
  border-radius: var(--r-control);
  font-size: 0.875rem;
  color: var(--fg-muted);
  transition: background .15s, color .15s;
}

.settings-nav:hover {
  background: var(--inset);
}

.settings-nav.active {
  background: var(--inset);
  color: var(--fg);
  font-weight: 600;
}

.settings-group {
  margin: 0.75rem 0.75rem 0.25rem;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-subtle);
}

.settings-group:first-child {
  margin-top: 0.25rem;
}

/* TEAM: WHAT EACH ROLE CAN DO, THEN WHO HAS WHICH.
   The two roles are explained once, side by side, at the top -- so the role
   menu on each person's row never needs explaining. A role is shown the same
   way everywhere (role-badge): red outline for Admin, plain for Technician. */

.team-roles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border: var(--bw) solid var(--line-soft);
  border-radius: var(--r-box);
  background: var(--inset);
}

.team-role-name {
  margin-bottom: 0.375rem;
}

.team-role-can {
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--fg-muted);
}

.team-role-rule {
  grid-column: 1 / -1;
  font-size: 0.875rem;
  color: var(--fg-subtle);
  padding-top: 0.625rem;
  border-top: var(--bw) solid var(--line-soft);
}

@media (max-width: 639.98px) {
  .team-roles {
    grid-template-columns: minmax(0, 1fr);
  }
}

.role-badge {
  display: inline-block;
  padding: 0.0625rem 0.5rem;
  border-radius: var(--r-control);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.5;
  border: var(--bw) solid var(--edge-soft);
  color: var(--fg-muted);
}

.role-badge-admin {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}

/* One row per person: who they are on the left, their role and the one thing
   you might do to them on the right. Flat rows inside one box, not a card per
   person. */

.team-list {
  border: var(--bw) solid var(--line-soft);
  border-radius: var(--r-box);
  overflow: hidden;
}

.team-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.625rem 0.875rem;
  background: var(--card);
}

.team-row + .team-row {
  border-top: var(--bw) solid var(--line-soft);
}

.team-row.is-removed {
  background: var(--inset);
}

.team-who {
  min-width: 0;
}

.team-name {
  font-size: 0.9375rem;
  color: var(--fg);
  font-weight: 600;
}

.team-sub {
  font-size: 0.875rem;
  color: var(--fg-subtle);
}

.team-you {
  margin-left: 0.375rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--fg-subtle);
}

.team-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

.team-role-select {
  min-width: 8.5rem;
  padding: 0.3125rem 0.5rem;
  border-radius: var(--r-control);
  font-size: 0.875rem;
  background: var(--inset);
  color: var(--fg);
  border: var(--bw) solid var(--edge);
}

.team-role-select:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.team-role-select:disabled {
  opacity: 1;
  color: var(--fg-subtle);
  border-color: var(--line-soft);
}

@media (max-width: 639.98px) {
  .team-row {
    flex-wrap: wrap;
  }

  .team-actions {
    width: 100%;
    justify-content: space-between;
  }
}

/* Quiet text buttons for the things done rarely: a new link, removing someone.
   Underlined so they read as actions, never as a third and fourth primary. */

.team-link {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--fg-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--edge-soft);
  padding: 0.25rem 0;
  transition: color .15s ease;
}

.team-link:hover {
  color: var(--fg);
  text-decoration-color: currentColor;
}

.team-link-danger {
  color: var(--danger);
}

.team-link-danger:hover {
  color: var(--danger);
}

.team-more > summary {
  cursor: pointer;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--fg-muted);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

.team-more > summary::-webkit-details-marker {
  display: none;
}

.team-more > summary::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .2s cubic-bezier(0.23, 1, 0.32, 1);
}

.team-more[open] > summary::before {
  transform: rotate(45deg);
}

.team-more > summary:hover {
  color: var(--fg);
}

@media (prefers-reduced-motion: reduce) {
  .team-more > summary::before {
    transition: none;
  }
}

/* Time saved: which period is on screen. One menu; date boxes only for "Pick dates". */

.roi-period {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 0.75rem;
  margin-bottom: 1rem;
}

.roi-period-label {
  font-size: 0.875rem;
  color: var(--fg-muted);
  align-self: center;
}

.roi-date {
  display: grid;
  gap: 0.25rem;
  font-size: 0.875rem;
  color: var(--fg-subtle);
}

.roi-date input {
  padding: 0.3125rem 0.5rem;
  border-radius: var(--r-control);
  font-size: 0.875rem;
  background: var(--inset);
  color: var(--fg);
  border: var(--bw) solid var(--edge);
}

/* A PHONE GETS A SHEET, NOT A SHRUNKEN WINDOW. Measured at 390px: the old
   modal left a 128px menu and a 200px column for the content, so every
   setting wrapped word by word. Below 640px it fills the screen, and the
   menu becomes one scrolling row of tabs above the content. */

@media (max-width: 639.98px) {
  #settings-modal {
    padding: 0;
  }

  #settings-modal > .dialog {
    max-width: none;
    max-height: none;
    height: 100%;
    border: 0;
    border-radius: 0;
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
  }

  #settings-body {
    flex-direction: column;
  }

  #settings-menu {
    width: 100%;
    flex-direction: row;
    align-items: center;
    gap: 0.25rem;
    overflow-x: auto;
    border-right: 0;
    border-bottom: 1px solid var(--edge-soft);
    padding: 0.5rem;
  }

  #settings-menu .settings-group {
    display: none;
  }

  #settings-menu .settings-nav {
    width: auto;
    flex: none;
    margin: 0;
    white-space: nowrap;
  }

  #settings-menu > div {
    margin: 0 0 0 auto;
    padding: 0;
    border: 0;
    flex: none;
  }

  #settings-menu > div button {
    white-space: nowrap;
  }
}

/* ------------------------------------------------------------------------ */

/* Legal pages (/terms, /privacy). Plain long-form prose -- these are the    */

/* only pages in the app that are read top to bottom rather than scanned.    */

/* ------------------------------------------------------------------------ */

.wiq-legal h2 {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--fg);
  margin: 1.5rem 0 0.5rem;
}

.wiq-legal h2:first-child {
  margin-top: 0;
}

.wiq-legal p {
  margin: 0 0 0.75rem;
}

.wiq-legal ul {
  margin: 0 0 0.75rem;
  padding-left: 1.1rem;
  list-style: disc;
}

.wiq-legal li {
  margin-bottom: 0.35rem;
}

.wiq-legal strong {
  color: var(--fg);
  font-weight: 600;
}

.wiq-legal a {
  color: var(--accent);
  text-decoration: underline;
}

/* ---- Toggle feedback (moved here from an inline \3c style> in index.html) ----
   The mic breathes with a red ping while listening, and "Listen" while it
   reads aloud; diagram mode shows a static corner dot while ON. A tap on a
   toggle settles from a slight squash -- no overshoot, it is a tool. */

.visual-on {
  position: relative;
}

.visual-on::after {
  content: '';
  position: absolute;
  top: 3px;
  right: 3px;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: #fff;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes wiq-pop {
    from {
      transform: scale(.97);
    }

    to {
      transform: scale(1);
    }
  }

  .wiq-pop {
    animation: wiq-pop 180ms var(--ease-out);
  }

  /* A ring that pulses outward; the button itself stays put, because it is
     the thing being pressed to stop. */

  @keyframes wiq-listen {
    0% {
      box-shadow: 0 0 0 0 var(--accent-ring);
    }

    70%, 100% {
      box-shadow: 0 0 0 10px transparent;
    }
  }

  .mic-listening {
    animation: wiq-listen 1.2s ease-in-out infinite;
  }

  .speak-active {
    animation: wiq-listen 1.4s ease-in-out infinite;
    border-radius: var(--r-control);
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Motionless: the active state still visibly changes. */

  .mic-listening, .speak-active {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
}

/* ======================================================================== */

/* COMPONENTS -- one definition per kind of control (premium UI phase 4).   */

/*                                                                          */

/* Before this, a primary button was written out as a utility string in    */

/* 30-odd places, each a little different. These classes are the one       */

/* definition; spacing and layout utilities still go beside them in the     */

/* markup. BOTH layouts, so they live above "THE NEW LAYOUT" marker.        */

/*                                                                          */

/* Motion (Emil Kowalski): a press scales to .97 with the strong ease-out;  */

/* transitions name their properties (never `all`); hover changes only      */

/* where there is a real hover (a pointer, not a finger).                   */

/* ======================================================================== */

@keyframes wiq-fade-in {
  from {
    opacity: 0;
  }
}

@keyframes wiq-dialog-in {
  from {
    opacity: 0;
    transform: scale(.96);
  }
}

/* EVERY button answers the hand, not only the ones migrated to .btn: a press
   settles to .97 (Emil Kowalski -- "the interface heard you"). In the base
   layer, so a button's own transition utility still wins; the :active rule is
   unlayered so it applies over any transform utility while held. */

@media (prefers-reduced-motion: no-preference) {
  button:not(:disabled):active {
    transform: scale(.97);
  }
}

/* ---- Text size and density (Settings, per device) -------------------------
   boot-theme.js sets html[data-text] and html[data-density] before first paint.
   TEXT SIZE IS A MULTIPLIER, not a size: everything is in rem, so scaling the
   root scales the whole app, and the new layout's screen-size steps below
   multiply by the same number instead of being overridden by it. */

html {
  font-size: calc(var(--text-scale, 1) * 100%);
}

html[data-text="small"] {
  --text-scale: .9375;
}

html[data-text="large"] {
  --text-scale: 1.125;
}

html[data-text="xl"]    {
  --text-scale: 1.25;
}

/* Compact: more rows on the screen at once, for the office desktop. Comfortable
   (no attribute) is the default and is the app as designed. */

html[data-density="compact"] #local-list li.group,
html[data-density="compact"] #doc-list li {
  padding-top: .2rem;
  padding-bottom: .2rem;
}

html[data-density="compact"] .wiq-answer {
  line-height: 1.55;
}

html[data-density="compact"] .wiq-answer p {
  margin: .4rem 0;
}

html[data-density="compact"] #messages > * + * {
  margin-top: .75rem;
}

/* The question box's hint is one line, cut with an ellipsis: wrapped onto two
   lines on a phone it doubled the box's height before anything was typed. */

#question::-moz-placeholder {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#question::placeholder {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- search results: five, then folds (both layouts; 2026-10-03) -------- */

.find-head {
  padding: 0 0.375rem 0.375rem;
  font-size: calc(var(--text-scale, 1) * 14px);
  font-weight: 700;
  color: var(--fg);
}

.find-section + .find-section {
  margin-top: 0.75rem;
}

.find-fold {
  border-top: var(--bw) solid var(--edge-soft);
}

.find-fold-summary {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  min-height: 2.75rem;
  padding: 0.625rem 0.375rem;
  cursor: pointer;
  list-style: none;
  font-size: calc(var(--text-scale, 1) * 14px);
  font-weight: 600;
  color: var(--fg);
}

.find-fold-summary::-webkit-details-marker {
  display: none;
}

.find-fold-summary::before {
  content: '';
  width: 0.45rem;
  height: 0.45rem;
  flex: none;
  align-self: center;
  border-right: 2px solid var(--fg-muted);
  border-bottom: 2px solid var(--fg-muted);
  transform: rotate(-45deg);
  margin-right: 0.25rem;
}

.find-fold[open] > .find-fold-summary::before {
  transform: rotate(45deg);
}

@media (hover: hover) {
  .find-fold-summary:hover {
    color: var(--accent);
  }
}

.find-fold-summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-control);
}

.find-fold-count {
  font-weight: 500;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.find-fold-note {
  width: 100%;
  padding-left: 1.2rem;
  font-weight: 400;
  color: var(--fg-muted);
}

.find-fold-rows {
  padding-bottom: 0.5rem;
}

/* The other-languages fold sits behind a heavier rule: a different shelf. */

.find-away-rule {
  margin-top: 1.25rem;
  border-top: 2px solid var(--edge);
}

.find-section.find-away-rule + .find-section {
  margin-top: 0;
}

.find-away-rule + .find-section .find-fold {
  border-top: 0;
}

#question::-moz-placeholder {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#question::placeholder {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ======================================================================== */

/* THE NEW LAYOUT -- a front door, a library page, a chat page.              */

/*                                                                          */

/* EVERY RULE BELOW IS SCOPED TO html.layout-new (or hides .lx-only when it */

/* is absent). The classic layout must render exactly as it did at the      */

/* `classic-ui` tag, and the only way to guarantee that is for none of this */

/* to reach it. See static/js/layout.js for why this is one page with two   */

/* presentations rather than two pages.                                     */

/*                                                                          */

/* The sizes are the measured problem, reversed: the classic library is    */

/* 12px text with 10px counts, 14px tick boxes, 36px buttons and actions    */

/* that stay invisible until hover, and its 44px touch targets are switched */

/* off on desktop -- the machine the mechanics actually use.                */

/* ======================================================================== */

/* Controls that exist only in the new layout. */

html:not(.layout-new) .lx-only {
  display: none !important;
}

/* ---- THE ALTERNATIVE LAYOUT'S SIDEBAR (2026-10-19) ------------------------
   One library at a time, chosen with the switch at the top (#alt-view); no
   folding; larger type and controls. Reported: "even when in uploaded
   manuals, it still shows the ones from on this computer, and the side panel
   is a mess with folding compartments everywhere -- make everything more
   visible and larger". The new layout does the same through data-mode. */

html:not(.layout-new) .alt-view {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.375rem;
  margin-top: 0.625rem;
}

html:not(.layout-new) .alt-view-btn {
  padding: 0.625rem 0.5rem;
  border-radius: var(--r-control);
  font-size: 1rem;
  font-weight: 600;
  background: var(--card);
  color: var(--fg-muted);
  border: var(--bw) solid var(--edge);
  transition: background-color .15s ease, color .15s ease, transform .16s ease-out;
}

html:not(.layout-new) .alt-view-btn:hover {
  color: var(--fg);
  border-color: var(--accent);
}

html:not(.layout-new) .alt-view-btn[aria-pressed="true"] {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: #fff;
}

html:not(.layout-new) .alt-view-btn:active {
  transform: scale(.97);
}

html:not(.layout-new) .alt-view-btn:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

html:not(.layout-new)[data-view="local"] #upload-card,
html:not(.layout-new)[data-view="local"] #uploaded-split,
html:not(.layout-new)[data-view="uploaded"] #local-panel,
html:not(.layout-new)[data-view="uploaded"] #local-split,
html:not(.layout-new) #source-switch,
html:not(.layout-new) .sidebar-collapse,
html:not(.layout-new) .library-split {
  display: none !important;
}

html:not(.layout-new) #setup-body,
html:not(.layout-new) #local-split-body,
html:not(.layout-new) #uploaded-split-body {
  display: block !important;
}

html:not(.layout-new) #library-body {
  display: flex !important;
}

/* ONE SCROLL, NOT TWO HALVES. The chooser, its card and the library sit in a
   single column that scrolls as one; the halves each scrolled on their own
   and cut the upload box off on a laptop screen. */

html:not(.layout-new) #library-panel {
  overflow-y: auto;
  overscroll-behavior: contain;
}

html:not(.layout-new) #setup-section,
html:not(.layout-new) #library-section,
html:not(.layout-new) #library-body {
  flex: 0 0 auto;
  min-height: auto;
}

html:not(.layout-new) #setup-body,
html:not(.layout-new) #library-lists {
  overflow: visible;
  min-height: auto;
  flex: 0 0 auto;
}

/* Larger: the 14px floor becomes the body size, and everything steps up. */

@media (min-width: 640px) {
  html:not(.layout-new) #sidebar {
    width: 24rem;
  }
}

html:not(.layout-new) #sidebar .text-2xs {
  font-size: 0.9375rem;
}

html:not(.layout-new) #sidebar .text-xs {
  font-size: 1rem;
}

html:not(.layout-new) #sidebar .text-sm {
  font-size: 1.0625rem;
}

html:not(.layout-new) #sidebar .btn-sm {
  padding: 0.5rem 0.875rem;
  font-size: 0.9375rem;
}

/* ---- one size per kind of screen --------------------------------------- */

/* Reported on a 27" 2560x1440 monitor: "it stretches out and leaves empty
   space on the bottom". Measured: the page filled all 1440px, but everything
   in it was sized for a laptop -- the door a 960px column holding a third of
   the screen, the library's cards ending two-thirds of the way down.

   So the base size steps up with the screen, and every size in this layout is
   in rem so it all steps up together: text, cards, buttons, gutters, columns.
   Each tier needs the HEIGHT as well as the width. A wide but short window --
   a browser not maximised, an ultrawide, a laptop at 125% scaling -- stays at
   the laptop size, because bigger type there only pushes the library off the
   bottom. Heights are for a maximised browser (the taskbar and tabs take
   ~130px), so a 1080p monitor is ~950px tall and a 1440p one ~1310px.

     phone / tablet / laptop     16px   (the base; nothing changes)
     1600+ wide, 800+ tall       17px   large laptops, 1600x900 monitors
     1900+ wide, 900+ tall       18px   1080p monitors
     2400+ wide, 1250+ tall      20px   1440p monitors, 27"
     3200+ wide, 1700+ tall      24px   4K at 100% scaling                  */

@media (min-width: 1600px) and (min-height: 800px)  {
  .layout-new {
    font-size: calc(var(--text-scale, 1) * 17px);
  }
}

@media (min-width: 1900px) and (min-height: 900px)  {
  .layout-new {
    font-size: calc(var(--text-scale, 1) * 18px);
  }
}

@media (min-width: 2400px) and (min-height: 1250px) {
  .layout-new {
    font-size: calc(var(--text-scale, 1) * 20px);
  }
}

@media (min-width: 3200px) and (min-height: 1700px) {
  .layout-new {
    font-size: calc(var(--text-scale, 1) * 24px);
  }
}

/* Settings -> Display: in BOTH layouts, so styled unscoped. */

.disp-opt {
  min-height: 44px;
  padding: 0 16px;
  border-radius: var(--r-control);
  font-size: 0.95rem;
  font-weight: 500;
  border: var(--bw) solid var(--edge);
  background: var(--inset);
  color: var(--fg-muted);
  transition: background .15s, color .15s, border-color .15s;
}

.disp-opt:hover {
  color: var(--fg);
}

.disp-opt[aria-pressed="true"] {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: #fff;
}

/* ---- the screens: which region is on the page ------------------------- */

.layout-new #lx-door {
  display: none;
}

.layout-new[data-screen="door"] #lx-door {
  display: flex;
}

.layout-new[data-screen="door"] #sidebar,
.layout-new[data-screen="door"] #chat-section {
  display: none !important;
}

.layout-new[data-screen="library"] #chat-section {
  display: none !important;
}

.layout-new[data-screen="chat"] #sidebar {
  display: none !important;
}

/* No drawer in a layout where the library IS the page. */

.layout-new #nav-toggle, .layout-new #nav-backdrop {
  display: none !important;
}

@media (max-width: 767px) {
  .layout-new #sidebar {
    position: static;
    transform: none;
    box-shadow: none;
    padding-top: 0;
    padding-bottom: 0;
    padding-left: 0;
  }
}

/* ---- the header ------------------------------------------------------- */

.layout-new #app-header > div {
  flex-wrap: wrap;
  row-gap: 0.5rem;
}

.layout-new .lx-headnav {
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: var(--r-box);
  background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.14);
}

.layout-new[data-screen="door"] .lx-headnav {
  display: none;
}

.layout-new .lx-mode {
  min-height: 40px;
  padding: 0 14px;
  border-radius: var(--r-control);
  font-size: 0.9rem;
  font-weight: 600;
  color: #c6cdd6;
  background: transparent;
  white-space: nowrap;
}

.layout-new .lx-mode[aria-pressed="true"] {
  background: #fff;
  color: var(--header);
}

.layout-new .lx-headbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  min-width: 44px;
  padding: 0 12px;
  border-radius: var(--r-control);
  font-size: 0.9rem;
  font-weight: 600;
  color: #f3f5f7;
  border: 1px solid rgba(255,255,255,.22);
  background: transparent;
}

.layout-new .lx-headbtn:hover {
  background: rgba(255,255,255,.1);
}

.layout-new .lx-on-chat {
  display: none;
}

.layout-new[data-screen="chat"] .lx-on-chat {
  display: inline-flex;
}

/* The theme toggle already lives in the corner; make it a real target. */

.layout-new #theme-toggle {
  min-width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
}

.layout-new #theme-toggle svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* One row on a phone. Measured at 400px: the brand's subtitle pushed the
   theme and settings buttons onto a second line and the header took 117px --
   a seventh of the screen before any manual appeared. The door repeats the
   subtitle, so nothing is lost by dropping it here. */

@media (max-width: 520px) {
  .layout-new .lx-headlabel {
    display: none;
  }

  .layout-new #brand-home p,
  .layout-new #brand-home h1 > span {
    display: none;
  }
}

/* ---- the front door --------------------------------------------------- */

/* CENTRED WITH margin:auto, NOT align-items:center. Found on a 400px screen:
   when the door is taller than the space under the header, align-items:center
   pushes the overflow UP as well as down -- and the top half is then above the
   scroll origin, where no scrolling can reach it. The logo simply vanished.
   An auto margin centres when there is room and gives way when there is not. */

.layout-new #lx-door {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(1.5rem, 5vw, 4rem) clamp(1rem, 4vw, 3rem);
}

.lx-door-inner {
  width: 100%;
  max-width: 60rem;
  margin-block: auto;
}

.lx-logo {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: clamp(1.5rem, 4vw, 2.75rem);
}

/* Wider than a phone, the header bar already shows the logo, the name and the
   tagline, so the door said them twice on one screen. The question leads
   instead. On a phone the header drops its tagline, so the door keeps it. */

@media (min-width: 521px) {
  .layout-new #lx-door .lx-logo {
    display: none;
  }
}

.lx-logo svg {
  width: clamp(2.75rem, 5vw, 3.6rem);
  height: auto;
  flex: none;
}

.lx-logo .lg-1 {
  fill: var(--logo-1);
}

.lx-word {
  font-weight: 800;
  font-size: clamp(1.5rem, 3vw, 1.9rem);
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--fg);
}

.lx-tagline {
  display: block;
  font-weight: 400;
  font-size: 0.9rem;
  letter-spacing: 0;
  color: var(--fg-subtle);
  margin-top: 0.35rem;
}

.lx-hi {
  font-size: clamp(1.05rem, 2vw, 1.25rem);
  font-weight: 500;
  color: var(--fg-muted);
  margin: 0 0 0.35rem;
}

.lx-door-title {
  font-weight: 700;
  letter-spacing: -0.025em;
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  line-height: 1.08;
  margin: 0 0 0.75rem;
  color: var(--fg);
  text-wrap: balance;
}

.lx-door-sub {
  font-size: 1.0625rem;
  color: var(--fg-muted);
  margin: 0 0 clamp(1.4rem, 3vw, 2.1rem);
  max-width: 54ch;
  text-wrap: pretty;
}

.lx-doors {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .lx-doors {
    grid-template-columns: 1fr 1fr;
  }
}

.lx-door-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  text-align: left;
  padding: 1.4rem;
  border-radius: var(--r-box);
  border: var(--bw) solid var(--edge);
  background: var(--card);
  color: var(--fg);
  transition: border-color .16s, transform .16s;
}

.lx-door-card:hover {
  border-color: var(--accent);
}

/* The lift only under a real pointer: a finger fires hover on tap, and the
   card would jump under it. */

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .lx-door-card:hover {
    transform: translateY(-2px);
  }
}

.lx-dc-icon {
  width: 2.9rem;
  height: 2.9rem;
  border-radius: var(--r-box);
  display: grid;
  place-items: center;
  background: var(--flash);
  color: var(--accent);
}

.lx-dc-icon svg {
  width: 1.5rem;
  height: 1.5rem;
}

.lx-dc-title {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.lx-dc-desc {
  font-size: 0.975rem;
  color: var(--fg-muted);
  line-height: 1.5;
}

.lx-dc-count {
  font-size: 0.875rem;
  color: var(--fg-subtle);
  font-variant-numeric: tabular-nums;
}

.lx-dc-go {
  margin-top: 0.15rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent);
}

/* ---- the library page: the sidebar, given the whole page -------------- */

.layout-new #sidebar {
  width: 100%;
  max-width: none;
  flex: 1 1 auto;
  border-right: 0;
  font-size: 1rem;
}

/* The two halves were a split of a cramped column. On a page the folder or
   upload controls take their natural height and the library fills the rest. */

/* THE PAGE SCROLLS, NOT A BOX INSIDE IT. The classic list is an inner
   scroller given whatever height the column has left. On a page that meant,
   measured on a 600px-tall screen with the folder warning showing, a library
   of four manuals squeezed into one visible line above the ask bar. Workshop
   laptops are often 768px tall. So the sections take their natural height,
   #sidebar is the scroller, and the ask bar sticks to the bottom of it. */

.layout-new #sidebar {
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* The tab panels are flex:1 / min-height:0 -- fixed to the column's leftover
   height. Measured: #library-panel 500px tall holding 1,016px of library, the
   rest spilling out underneath the ask bar and the account footer. */

.layout-new #library-panel,
.layout-new #chats-panel {
  flex: 0 0 auto;
  min-height: auto;
}

.layout-new #setup-section,
.layout-new #library-section {
  flex: 0 0 auto !important;
  max-height: none;
  min-height: auto;
}

.layout-new #library-body {
  min-height: auto;
}

.layout-new #setup-body,
.layout-new #library-lists {
  flex: none;
  overflow: visible;
  min-height: auto;
}

/* sidebar.js persists a collapsed half as an INLINE display:none. Collapse in
   classic, switch layouts, and the folder picker would be gone with no chevron
   to bring it back. On a whole page there is nothing to collapse, so the
   bodies are forced open and the chevrons hidden. */

.layout-new #setup-body {
  display: block !important;
}

.layout-new #library-body {
  display: flex !important;
}

.layout-new .sidebar-collapse, .layout-new .library-split {
  display: none !important;
}

/* Which library this page is for. Only controls that act on the OTHER source
   are hidden -- checked in the code, not assumed: toggleAll, the type chips and
   Move/Remove all act on state.selected / state.docType, which local mode
   never reads. Every one of them is on the uploaded page. */

.layout-new[data-mode="local"] #upload-card,
.layout-new[data-mode="local"] #uploaded-split,
.layout-new[data-mode="local"] #doc-filters,
.layout-new[data-mode="local"] #scope-header,
.layout-new[data-mode="local"] #remove-header,
.layout-new[data-mode="local"] #move-header,
.layout-new[data-mode="local"] #remove-bar,
.layout-new[data-mode="local"] #move-bar {
  display: none !important;
}

.layout-new[data-mode="uploaded"] #local-panel,
.layout-new[data-mode="uploaded"] #local-split {
  display: none !important;
}

/* Readable text. Every small size in the library comes up; nothing is below
   the 14px used for secondary detail, and the reading size is 16px. */

.layout-new #sidebar .text-xs {
  font-size: 1rem;
  line-height: 1.45;
}

.layout-new #sidebar .text-2xs {
  font-size: 0.875rem;
  line-height: 1.4;
}

.layout-new #sidebar .text-sm {
  font-size: 1rem;
}

.layout-new #local-list li .text-fg-subtle,
.layout-new #doc-list .text-fg-subtle {
  font-size: 0.875rem;
}

/* Targets. The 44px floors that md:min-h-0 / md:min-w-0 cancelled on desktop
   come back -- those two classes appear only on controls that had a 44px floor
   on touch and nowhere else (checked). */

.layout-new .md\:min-h-0 {
  min-height: 44px;
}

.layout-new .md\:min-w-0 {
  min-width: 44px;
}

.layout-new #sidebar button,
.layout-new #sidebar select,
.layout-new #sidebar input[type="text"],
.layout-new #sidebar input[type="search"] {
  min-height: 44px;
}

.layout-new #sidebar input[type="checkbox"] {
  width: 1.4rem;
  height: 1.4rem;
  flex: none;
}

/* Rename and View on every row, always -- not only on hover. */

.layout-new #sidebar .md\:opacity-0 {
  opacity: 1;
}

/* ======================================================================== */

/* THE LIBRARY PAGE, AS PROPOSED -- not the old sidebar made wider.          */

/*                                                                          */

/* Reported on sight: "it's only covering 60% of the page and just has old  */

/* layouts in a new layout". Measured at 1600px: the list was 1,008px wide  */

/* (63%) under the sidebar's own headings, its stacked folder card, a full- */

/* width sort box and a one-column list. The proposal was a page heading, a */

/* big search, a slim folder bar and a GRID of manual cards across the page */

/* -- so that is what the same elements are arranged into here.             */

/* ======================================================================== */

/* The whole width, with a gutter -- the ask bar and account footer stay full
   bleed, so the gutter lives on the panels rather than on the scroller. */

.layout-new #sidebar {
  --lx-gutter: clamp(1rem, 3vw, 3rem);
}

.layout-new #lx-libhead,
.layout-new #lx-tabs,
.layout-new #library-panel,
.layout-new #chats-panel {
  padding-inline: var(--lx-gutter);
}

/* The page heading. */

.layout-new #lx-libhead {
  display: block;
  padding-top: clamp(1.25rem, 3vw, 2.25rem);
  padding-bottom: 0.25rem;
}

.layout-new #lx-lib-title {
  margin: 0 0 0.3rem;
  font-size: clamp(1.4rem, 2.4vw, 1.85rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--fg);
}

.layout-new #lx-lib-sub {
  margin: 0;
  font-size: 1rem;
  color: var(--fg-muted);
  max-width: 70ch;
}

/* Library | Chats, as a small switch under the heading rather than a bar of
   two half-width tabs across the top of a column. */

.layout-new #lx-tabs {
  justify-content: flex-start;
  gap: 0.35rem;
  border-bottom: 0;
  padding-top: 0.9rem;
  padding-bottom: 0.25rem;
}

.layout-new #lx-tabs .sidebar-tab {
  flex: 0 0 auto;
  min-height: 42px;
  padding-inline: 1rem;
  font-size: 0.95rem;
}

/* The sidebar's own section headings go; the page heading replaces them.
   They hold heading text and the fold arrows, which are already hidden --
   nothing a person can press. The split header's count is shown in the page
   heading instead (layout.js copies it). */

.layout-new #setup-section > div:first-child,
.layout-new #library-section > div:first-child,
.layout-new #local-split > div:first-child,
.layout-new #uploaded-split > div:first-child {
  display: none;
}

.layout-new #setup-section {
  border-bottom: 0;
}

.layout-new #setup-body {
  padding: 0.75rem 0 0;
}

.layout-new #local-split-body, .layout-new #uploaded-split-body {
  padding: 0;
}

/* The folder, as one bar: what it is and what you can do, on one line where
   the screen allows. Warnings and progress drop to their own line beneath.
   :not(.hidden) on every display rule -- local.js hides this panel outright in
   a browser that cannot read folders, and a display rule would out-rank that. */

.layout-new #local-panel:not(.hidden) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.75rem;
  padding: 0.85rem 1rem;
  border-radius: var(--r-box);
}

.layout-new #local-panel > * {
  margin: 0;
}

.layout-new #local-panel > div:first-child {
  flex: 1 1 12rem;
  margin: 0;
}

.layout-new #local-what {
  display: none;
}

.layout-new #local-hint {
  flex-basis: 100%;
  order: 9;
  font-size: 0.875rem;
}

.layout-new #local-disconnected,
.layout-new #local-folder-advice,
.layout-new #local-progress {
  flex-basis: 100%;
  order: 10;
}

.layout-new #local-panel > div:not(:first-child):not(#local-progress) {
  flex: 0 0 auto;
  margin: 0;
}

.layout-new #local-open-folder, .layout-new #local-open-file,
.layout-new #local-rescan, .layout-new #local-reconnect {
  flex: 0 0 auto;
  padding-inline: 1.1rem;
}

/* The uploaded side's equivalent: the drop zone as a bar, not a tall box. */

.layout-new #upload-card {
  padding: 0.85rem 1rem;
  border-radius: var(--r-box);
}

/* A search box worth aiming at. */

.layout-new #doc-search {
  min-height: 54px;
  font-size: 1.0625rem;
}

/* Sort and "show only these" on one row, sized to their words. */

.layout-new #local-sort-row:not(.hidden),
.layout-new #local-selected-row:not(.hidden) {
  display: inline-flex;
  vertical-align: middle;
  margin: 0.6rem 0.75rem 0.6rem 0;
  padding: 0;
}

.layout-new #local-sort {
  width: auto;
}

/* ---- the cards -------------------------------------------------------- */

/* One grid for the flat list (sorted, or a search's rows); a group -- a
   machine, or "other manuals that mention this" -- spans the full row with
   its own grid underneath. :has(> ul) is how a group is told from a card:
   the group <li> holds a list, a card never does. */

.layout-new #local-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  gap: 0.75rem;
  padding-bottom: 1.25rem;
}

.layout-new #local-list > li:has(> ul) {
  grid-column: 1 / -1;
  margin-top: 0.75rem;
}

.layout-new #local-list > li:has(> ul):first-child {
  margin-top: 0;
}

.layout-new[data-density="compact"] #local-list,
.layout-new[data-density="compact"] #local-list > li:has(> ul) > ul {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: 0.5rem;
}

.layout-new[data-density="compact"] #local-list li.group {
  padding: 0.6rem 0.7rem;
  min-height: 0;
  row-gap: 0.35rem;
}

.layout-new[data-density="compact"] .lx-folder-open {
  min-height: 4.25rem;
  padding: 0.75rem 0.9rem;
}

.layout-new #local-list > li:has(> ul) > ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  gap: 0.75rem;
  margin-top: 0.6rem;
}

/* Search results: each section spans the grid; its rows are the card grid.
   A folder's shelf holds the same sections inside its own card grid. */

.layout-new #local-list li.find-section {
  grid-column: 1 / -1;
}

.layout-new #local-list .find-best,
.layout-new #local-list .find-fold-rows {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  gap: 0.75rem;
  margin-top: 0.25rem;
}

.layout-new #local-list .find-head {
  font-size: 1.125rem;
}

.layout-new #local-list .find-fold-summary {
  font-size: 0.9375rem;
}

/* A machine's heading reads as a heading. */

.layout-new #local-list > li:has(> ul) > div {
  padding-inline: 0.15rem;
}

.layout-new #local-list .local-machine {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--fg);
}

/* Each manual, a card. */

.layout-new #local-list li.group,
.layout-new #local-list li.bg-inset {
  border: var(--bw) solid var(--edge-soft);
  background: var(--card);
  border-radius: var(--r-box);
  padding: 0.9rem 0.95rem;
  align-items: flex-start;
  min-height: 5.25rem;
}

.layout-new #local-list li.group:hover,
.layout-new #local-list li.bg-inset:hover {
  border-color: var(--edge);
  background: var(--card);
}

/* NO FADING. The classic list dims every unticked row to 55% so the ticked
   ones stand out. In a grid where most cards are unticked, that makes the
   whole library look switched off -- and dims the very names being scanned.
   The red border below already says which ones are in the next question. */

.layout-new #local-list li.group {
  opacity: 1;
}

/* Ticked means in the next question: say it with the border, not only the box.
   A search result (li.bg-inset) has its own tick since 2026-10-03. */

.layout-new #local-list li.bg-inset:has(.local-find-tick:checked),
.layout-new #local-list li.group:has(.local-tick:checked) {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* THE NAME GETS THE CARD. Measured: a 310px card gave its name 137px, because
   the tick and two 44px icon buttons sat on the same line -- "MAN D1556 /
   engine -- Repair / manual" over three lines. The actions move to their own
   row underneath, and say what they do rather than being bare icons. */

.layout-new #local-list li.group {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
  row-gap: 0.55rem;
}

.layout-new #local-list li.group > .local-tick {
  grid-row: 1;
  grid-column: 1;
  margin-top: 0.15rem;
}

.layout-new #local-list li.group > span {
  grid-row: 1;
  grid-column: 2 / -1;
}

.layout-new #local-list li.group > .local-rename {
  grid-row: 2;
  grid-column: 3;
}

.layout-new #local-list li.group > .local-view {
  grid-row: 2;
  grid-column: 4;
}

.layout-new #local-list .local-rename,
.layout-new #local-list .local-view {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0 0.75rem;
  border: var(--bw) solid var(--edge);
  border-radius: var(--r-control);
  background: var(--inset);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--fg-muted);
}

/* ⚠️ ONLY THE ICON BUTTONS ON A LIBRARY ROW GET A WORD ADDED. A search result's
   Rename button already SAYS "Rename" (local.js renderFindResults), and this
   rule written against every .local-rename in the list printed it twice --
   "RenameRename", reported from the live site. The library row's buttons are
   direct children of li.group; the search result's sit inside a span. */

.layout-new #local-list li.group > .local-rename::after {
  content: "Rename";
}

.layout-new #local-list li.group > .local-view::after {
  content: "View";
}

.layout-new #local-list .local-rename:hover,
.layout-new #local-list .local-view:hover {
  color: var(--fg);
  border-color: var(--accent);
}

/* A card has room: let names wrap instead of cutting them off. */

.layout-new #local-list .truncate {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

.layout-new #local-list li.group > span:first-of-type > span:first-child {
  font-weight: 600;
  margin-bottom: 0.2rem;
}

/* ---- the folders ------------------------------------------------------- */

/* A big library opens on one tile per series ("Fendt 700", "Fendt Katana",
   "Not sorted"); inside, a bar leads back out. See folderView in local.js. */

.layout-new #local-list .lx-folder-tile {
  display: flex;
}

/* "N manuals sit directly in this folder, so Fettlex cannot group them by
   machine" is the classic list's problem, and the folders answer it. Left up,
   it contradicts the page it sits on. */

.layout-new #local-folder-advice {
  display: none !important;
}

.lx-folder-open {
  flex: 1;
  display: grid;
  grid-template-columns: auto 1fr;
  -moz-column-gap: 0.85rem;
       column-gap: 0.85rem;
  row-gap: 0.2rem;
  align-items: center;
  text-align: left;
  min-height: 6rem;
  padding: 1.1rem 1.15rem;
  border: var(--bw) solid var(--edge);
  border-radius: var(--r-box);
  background: var(--card);
  color: var(--fg);
  transition: border-color .15s, transform .15s;
}

.lx-folder-open:hover {
  border-color: var(--accent);
}

@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .lx-folder-open:hover {
    transform: translateY(-1px);
  }
}

.lx-folder-open svg {
  grid-row: 1 / span 3;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0.5rem;
  border-radius: var(--r-control);
  background: var(--flash);
  color: var(--accent);
}

.lx-folder-name {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.lx-folder-n {
  font-size: 0.95rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.lx-folder-n b {
  color: var(--accent);
  font-weight: 600;
}

.lx-folder-subs {
  font-size: 0.875rem;
  color: var(--fg-subtle);
}

.lx-folder-unsorted .lx-folder-open {
  border-style: dashed;
}

.lx-folder-unsorted .lx-folder-open svg {
  background: var(--inset);
  color: var(--fg-subtle);
}

/* ⚠️ THE WAY BACK STAYS ON SCREEN. Asked for directly: "when trying to go back
   (back arrow) can you make it higher on the page ... so people can navigate
   easily". Measured before: at the top of a folder the bar sat halfway down the
   screen, under the heading, the folder card, the search box and the sort row;
   scrolled into the folder there was no way back on screen at all. So the bar
   pins to the top of the page while you are in a folder -- directly under the
   header -- and a solid background keeps the cards from showing through it. */

.layout-new #local-list .lx-folder-crumb {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  position: sticky;
  top: 0;
  z-index: 6;
  margin-inline: calc(-1 * var(--lx-gutter, 1rem));
  padding: 0.65rem var(--lx-gutter, 1rem);
  background: var(--canvas);
  border-bottom: 1px solid var(--edge-soft);
}

.lx-folder-back {
  min-height: 48px;
  padding: 0 1.1rem;
  border-radius: var(--r-control);
  font-size: 1rem;
  font-weight: 700;
  border: 2px solid var(--accent);
  background: var(--inset);
  color: var(--fg);
}

.layout-new .cover-note {
  font-size: 0.875rem;
}

.lx-folder-back:hover {
  border-color: var(--accent);
}

.lx-folder-here {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fg);
}

/* The uploaded manuals are cards already; put them in the same grid. */

.layout-new .mach-docs:not(.hidden) {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  gap: 0.75rem;
  padding-left: 0;
  margin-top: 0.5rem;
}

.layout-new .mach-name {
  font-size: 1.05rem;
}

/* ---- the ask bar ------------------------------------------------------ */

/* margin-top:auto pins it to the BOTTOM OF THE SCREEN when the library is
   short. Measured at 1440px tall with no folder open: sticky alone left it
   under the last card at 897px, with 470px of blank page below it. When the
   library is long, sticky keeps it on screen as the cards scroll past. */

.layout-new #lx-askbar {
  margin-top: auto;
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.8rem 1rem;
  background: var(--panel);
  border-top: 2px solid var(--accent);
  font-size: 1rem;
  color: var(--fg);
}

.layout-new #lx-askbar-text {
  flex: 1;
  min-width: 12rem;
}

.layout-new #lx-ask {
  min-height: 48px;
  padding: 0 1.25rem;
  border-radius: var(--r-control);
  font-size: 1rem;
  font-weight: 600;
  background: var(--accent-fill);
  color: #fff;
}

.layout-new #lx-ask:not(:disabled):hover {
  background: var(--accent-fill-hover);
}

.layout-new #lx-ask:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* ---- the chat page ---------------------------------------------------- */

.layout-new #chat-section {
  width: 100%;
}

/* NO SEARCH STRIP ON THIS PAGE. It said the machine and a count, and offered
   the library switch -- both already on screen, in the chat header (book by
   book) and the header bar (This computer | Uploaded). Measured at 1024x768 it
   was 70px of a 768px screen saying the same thing twice. The ask bar still
   reads its text (layout.js syncAskBar), which display:none does not stop. */

.layout-new #scope-bar {
  display: none !important;
}

.layout-new #messages {
  font-size: 1.0625rem;
}

.layout-new .wiq-answer {
  font-size: 1.0625rem;
}

.layout-new #question {
  font-size: 1.0625rem;
  min-height: 52px;
}

.layout-new #composer button {
  min-width: 48px;
  min-height: 48px;
}

.layout-new .source-btn {
  min-height: 44px;
  font-size: 0.9rem;
}

/* ---- the chat header: which books this chat is reading ----------------- */

/* ONE ROW: what it is reading, the books, and the two actions. It was three
   stacked blocks (label and buttons, then a row per chip) and measured 256px
   tall with three books ticked; the answer under it got 227px. The column is
   the answer's own width, centred. On a narrow screen the chips drop to a
   second row under the label and the buttons. */

.layout-new #lx-chathead {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
  row-gap: 0.45rem;
  padding: 0.55rem max(1rem, calc((100% - 56rem) / 2));
  background: var(--inset);
  border-bottom: 1px solid var(--edge);
}

.layout-new #lx-chathead > * {
  margin: 0;
}

.layout-new #lx-chathead .lx-ch-top {
  display: contents;
}

.layout-new #lx-chathead .lx-ch-label {
  grid-column: 1;
  grid-row: 1;
  flex: none;
  min-width: 0;
}

.layout-new #lx-chathead .lx-ch-chips {
  grid-column: 2;
  grid-row: 1;
  margin-top: 0;
  min-width: 0;
}

.layout-new #lx-chathead .lx-ch-acts {
  grid-column: 3;
  grid-row: 1;
  flex-wrap: nowrap;
}

.layout-new #lx-chathead .lx-ch-mix {
  grid-column: 1 / -1;
}

/* Folded, the row never wraps: the two chips shrink (down to 7rem, the rest of
   the name in the tooltip) so "+N more" stays on the same line. Opened, it
   wraps to show every book. */

.layout-new #lx-chathead .lx-ch-row {
  flex-wrap: nowrap;
}

.layout-new #lx-chathead .lx-ch-row.is-open {
  flex-wrap: wrap;
}

.layout-new #lx-chathead .lx-chip {
  flex: 0 1 auto;
  min-width: 7rem;
  max-width: 15rem;
}

.layout-new #lx-chathead .lx-chip-more {
  flex: none;
}

@media (max-width: 767.98px) {
  .layout-new #lx-chathead .lx-ch-chips {
    grid-column: 1 / -1;
    grid-row: 2;
  }
}

/* A PHONE: the chips scroll sideways in one row instead of wrapping (measured
   at 390px: two rows of chips put the header at 217px), and the library switch
   leaves the header on the chat page -- switching library ends the chat
   anyway, and it is one tap away on the library page. The header then fits
   one row. */

@media (max-width: 520px) {
  .layout-new #lx-chathead .lx-ch-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
  }

  .layout-new #lx-chathead .lx-ch-row::-webkit-scrollbar {
    display: none;
  }

  .layout-new #lx-chathead .lx-chip, .layout-new #lx-chathead .lx-chip-more {
    flex: none;
  }

  .layout-new[data-screen="chat"] .lx-headnav {
    display: none;
  }

  .layout-new #app-header > div {
    -moz-column-gap: 0.5rem;
         column-gap: 0.5rem;
    padding-inline: 0.75rem;
  }

  .layout-new #app-header .ml-auto {
    gap: 0.375rem;
  }

  .layout-new .lx-headbtn {
    padding: 0 0.6rem;
  }
}

.lx-ch-top {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.lx-ch-label {
  flex: 1;
  min-width: 8rem;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-subtle);
}

.lx-ch-acts {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.lx-ch-acts button {
  min-height: 44px;
  padding: 0 0.9rem;
  border-radius: var(--r-control);
  font-size: 0.95rem;
  font-weight: 600;
  border: var(--bw) solid var(--edge);
  background: var(--card);
  color: var(--fg);
}

.lx-ch-acts button:hover {
  border-color: var(--accent);
}

#lx-add-manual {
  color: var(--accent);
  border-style: dashed;
  background: transparent;
}

.lx-ch-chips {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.lx-ch-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.lx-chip {
  display: inline-flex;
  align-items: stretch;
  max-width: 100%;
  border-radius: 999px;
  border: var(--bw) solid var(--edge);
  background: var(--card);
  overflow: hidden;
}

.lx-chip-open {
  min-height: 40px;
  padding: 0 0.4rem 0 0.95rem;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--fg);
  background: transparent;
  text-align: left;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lx-chip-open:hover {
  color: var(--accent);
}

.lx-chip-x {
  min-width: 40px;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--fg-subtle);
  background: transparent;
  border-left: 1px solid var(--edge-soft);
}

.lx-chip-x:hover {
  color: var(--accent);
  background: var(--flash);
}

.lx-chip-more {
  min-height: 40px;
  padding: 0 0.9rem;
  border-radius: 999px;
  border: var(--bw) dashed var(--edge);
  background: transparent;
  color: var(--fg-muted);
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
}

.lx-chip-more:hover {
  color: var(--fg);
  border-color: var(--accent);
}

.lx-ch-empty {
  margin: 0;
  font-size: 0.95rem;
  color: var(--fg-muted);
}

/* One line per ticked book that covers several tractors -- full width under the
   chips (the chips row wraps), so the pill shape of a chip is left alone. */

.lx-ch-cover {
  flex-basis: 100%;
  margin: 0;
  font-size: 0.9rem;
  color: var(--fg-muted);
}

.lx-ch-cover-name {
  font-weight: 600;
  color: var(--fg);
}

.lx-ch-cover .cover-note {
  margin-top: 0;
  margin-left: 0.35rem;
  vertical-align: middle;
}

.lx-ch-mix {
  margin: 0.6rem auto 0;
  padding: 0.6rem 0.85rem;
  border-radius: var(--r-control);
  font-size: 0.925rem;
  line-height: 1.45;
  background: var(--warn-bg);
  border: var(--bw) solid var(--warn-border);
  color: var(--warn-fg);
}

/* ---- the pages an answer came from: open, and readable ----------------- */

.layout-new .sources-toggle {
  font-size: 0.95rem;
  min-height: 40px;
}

.layout-new .sources-toggle svg {
  width: 1.1rem;
  height: 1.1rem;
}

.layout-new .source-card {
  padding: 0.75rem 0.85rem;
  gap: 0.75rem;
  min-height: 44px;
}

.layout-new .source-card > span:first-child {
  width: 1.75rem;
  height: 1.75rem;
  font-size: 0.875rem;
  border-radius: var(--r-control);
}

.layout-new .source-card .text-2xs {
  font-size: 0.9rem;
}

.layout-new .source-card blockquote {
  font-size: 0.975rem;
  line-height: 1.5;
}

/* ---- the manual: the viewer's controls, finger-sized ------------------- */

/* SIZES ONLY -- never display. #viewer-download toggles .hidden when a manual
   has no original, and #viewer-lib-toggle is md:hidden; a display rule here
   would out-rank both and show buttons that are meant to be gone. */

.layout-new #viewer-page-prev, .layout-new #viewer-page-next,
.layout-new #viewer-zoom-out, .layout-new #viewer-zoom-in,
.layout-new #viewer-download, .layout-new #viewer-close,
.layout-new #viewer-lib-toggle {
  min-width: 44px;
  min-height: 44px;
}

.layout-new #viewer-page-input {
  min-height: 44px;
  width: 4.75rem;
  font-size: 1rem;
}

.layout-new #viewer-page-count {
  font-size: 1rem;
}

.layout-new #viewer-title {
  font-size: 1.05rem;
}

.layout-new #viewer-search {
  min-height: 44px;
  font-size: 1rem;
}

.layout-new #viewer-library .text-sm {
  font-size: 1rem;
}

.layout-new #viewer-library .text-2xs {
  font-size: 0.875rem;
}

.layout-new #viewer-text {
  font-size: 1rem;
}

.placeholder\:text-fg-subtle::-moz-placeholder {
  color: var(--fg-subtle);
}

.placeholder\:text-fg-subtle::placeholder {
  color: var(--fg-subtle);
}

.first\:mt-0:first-child {
  margin-top: 0px;
}

.focus-within\:border-brand:focus-within {
  border-color: var(--accent);
}

.focus-within\:ring-2:focus-within {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus-within\:ring-brand-ring:focus-within {
  --tw-ring-color: var(--accent-ring);
}

.hover\:border-brand:hover {
  border-color: var(--accent);
}

.hover\:border-danger:hover {
  border-color: var(--danger);
}

.hover\:border-danger-border:hover {
  border-color: var(--danger-border);
}

.hover\:border-info-border:hover {
  border-color: var(--info-border);
}

.hover\:border-line-soft:hover {
  border-color: var(--edge-soft);
}

.hover\:bg-brand-fill:hover {
  background-color: var(--accent-fill);
}

.hover\:bg-brand-fill-hover:hover {
  background-color: var(--accent-fill-hover);
}

.hover\:bg-brand-soft:hover {
  background-color: var(--accent-soft);
}

.hover\:bg-card:hover {
  background-color: var(--card);
}

.hover\:bg-danger-bg:hover {
  background-color: var(--danger-bg);
}

.hover\:bg-inset:hover {
  background-color: var(--inset);
}

.hover\:bg-white\/10:hover {
  background-color: rgb(255 255 255 / 0.1);
}

.hover\:bg-white\/5:hover {
  background-color: rgb(255 255 255 / 0.05);
}

.hover\:text-brand:hover {
  color: var(--accent);
}

.hover\:text-brand-strong:hover {
  color: var(--accent-strong);
}

.hover\:text-danger:hover {
  color: var(--danger);
}

.hover\:text-fg:hover {
  color: var(--fg);
}

.hover\:text-fg-muted:hover {
  color: var(--fg-muted);
}

.hover\:text-info:hover {
  color: var(--info);
}

.hover\:text-white:hover {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

.hover\:underline:hover {
  text-decoration-line: underline;
}

.focus\:border-brand:focus {
  border-color: var(--accent);
}

.disabled\:cursor-not-allowed:disabled {
  cursor: not-allowed;
}

.disabled\:opacity-40:disabled {
  opacity: 0.4;
}

.disabled\:opacity-60:disabled {
  opacity: 0.6;
}

.dark\:block:is(.dark *) {
  display: block;
}

.dark\:hidden:is(.dark *) {
  display: none;
}

@media (min-width: 640px) {
  .sm\:mx-1 {
    margin-left: 0.25rem;
    margin-right: 0.25rem;
  }

  .sm\:block {
    display: block;
  }

  .sm\:inline {
    display: inline;
  }

  .sm\:w-44 {
    width: 11rem;
  }

  .sm\:w-64 {
    width: 16rem;
  }

  .sm\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sm\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .sm\:gap-1\.5 {
    gap: 0.375rem;
  }

  .sm\:gap-3 {
    gap: 0.75rem;
  }

  .sm\:p-9 {
    padding: 2.25rem;
  }

  .sm\:px-4 {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  .sm\:px-5 {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }

  .sm\:text-3xl {
    font-size: 1.875rem;
    line-height: 2.25rem;
  }

  .sm\:text-4xl {
    font-size: 2.25rem;
    line-height: 2.5rem;
  }
}

@media (min-width: 768px) {
  .md\:col-span-2 {
    grid-column: span 2 / span 2;
  }

  .md\:-mt-0\.5 {
    margin-top: -0.125rem;
  }

  .md\:hidden {
    display: none;
  }

  .md\:h-3\.5 {
    height: 0.875rem;
  }

  .md\:min-h-0 {
    min-height: 0px;
  }

  .md\:w-3\.5 {
    width: 0.875rem;
  }

  .md\:min-w-0 {
    min-width: 0px;
  }

  .md\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .md\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .md\:grid-cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .md\:grid-cols-5 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .md\:divide-x > :not([hidden]) ~ :not([hidden]) {
    --tw-divide-x-reverse: 0;
    border-right-width: calc(1px * var(--tw-divide-x-reverse));
    border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
  }

  .md\:divide-line-soft > :not([hidden]) ~ :not([hidden]) {
    border-color: var(--edge-soft);
  }

  .md\:px-8 {
    padding-left: 2rem;
    padding-right: 2rem;
  }

  .md\:py-0 {
    padding-top: 0px;
    padding-bottom: 0px;
  }

  .md\:py-0\.5 {
    padding-top: 0.125rem;
    padding-bottom: 0.125rem;
  }

  .md\:py-1 {
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
  }

  .md\:py-1\.5 {
    padding-top: 0.375rem;
    padding-bottom: 0.375rem;
  }

  .md\:pl-5 {
    padding-left: 1.25rem;
  }

  .md\:opacity-0 {
    opacity: 0;
  }

  .md\:first\:pl-0:first-child {
    padding-left: 0px;
  }

  .group:hover .md\:group-hover\:opacity-100 {
    opacity: 1;
  }
}

@media (min-width: 1024px) {
  .lg\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media print {
  .print\:hidden {
    display: none;
  }
}
