/* listing_write design system -- shared foundation for the operations desk.
 *
 * This is an internal desk where five people move real inventory across
 * twelve channels. The screen's job is to state what is true right now
 * and what the next safe action is; it is never trying to impress
 * anybody. Everything below follows from that: bright tinted-zinc
 * neutrals, thin borders, compact type, one blue for action, and status
 * color reserved for status.
 *
 * NAMESPACE
 *   Every token is `--lw-*` and every primitive is `.lw-*`. The three
 *   existing page stylesheets (app.css, matrix.css, admin-auth.css)
 *   declare their own `--ink`, `--line`, `--blue` and `.btn` at :root and
 *   at element level. An unprefixed name here would win or lose against
 *   them purely by <link> order -- a bug that appears on one page and not
 *   another. The prefix removes the question. Element-level defaults are
 *   wrapped in `:where()` so they carry zero specificity and every page
 *   stylesheet keeps overriding them during migration.
 *
 * DELIBERATELY ABSENT
 *   Gradients, glassmorphism/blur, drop shadows, webfonts, and any URL
 *   that leaves this host. Separation is done with a 1px border and a
 *   surface step, which stays legible at 100 rows and costs nothing to
 *   render. Overlays use a flat scrim rather than elevation.
 *
 * COLOR IS NEVER THE ONLY SIGNAL
 *   Every status primitive here is built to carry text. `.lw-dot` also
 *   varies in SHAPE per status, so an operator who cannot separate the
 *   hues still reads three different marks. Contrast ratios in the
 *   comments below are measured, and tests/webapp/test_design_system_css.py
 *   re-measures them on every run.
 */

:root {
  /* -- tinted zinc ramp ------------------------------------------------
     Cool-tinted rather than pure gray (blue channel runs a step above
     red/green), which keeps white surfaces from reading yellow next to
     the blue action color. Steps 25-300 are the surface/border range
     carried over from the existing matrix so the two look like one
     product; 500-900 are tuned for measured contrast, not copied. */
  --lw-zinc-0: #ffffff;
  --lw-zinc-25: #fafafa;
  --lw-zinc-50: #f4f4f5;
  --lw-zinc-100: #f1f1f3;
  --lw-zinc-200: #e4e4e7;
  --lw-zinc-300: #d4d4d8;
  --lw-zinc-400: #c4c4c8;   /* rules and dividers only -- never a mark */
  --lw-zinc-500: #8f8f99;   /* 3.15:1 on white: the lightest usable mark */
  --lw-zinc-600: #6b6b74;   /* 4.72:1 on --lw-canvas: lightest usable text */
  --lw-zinc-700: #52525b;
  --lw-zinc-800: #3f3f46;
  --lw-zinc-900: #18181b;

  /* -- surfaces --------------------------------------------------------
     Three steps, no more. canvas holds the page, surface holds content,
     sunken marks a header/footer band inside content. */
  --lw-canvas: var(--lw-zinc-50);
  --lw-surface: var(--lw-zinc-0);
  --lw-surface-sunken: var(--lw-zinc-25);
  --lw-border: var(--lw-zinc-200);
  --lw-border-strong: var(--lw-zinc-300);
  --lw-border-hair: var(--lw-zinc-100);
  --lw-scrim: rgba(24, 24, 27, 0.38);

  /* -- ink -------------------------------------------------------------
     Three text weights and one non-text mark. --lw-mark is the ONLY
     light value allowed to carry meaning, and only as a shape/boundary
     (3:1, WCAG 1.4.11); it is never text. */
  --lw-text: var(--lw-zinc-900);
  --lw-text-body: var(--lw-zinc-800);
  --lw-text-muted: var(--lw-zinc-600);
  --lw-mark: var(--lw-zinc-500);
  --lw-text-on-accent: var(--lw-zinc-0);

  /* -- action ----------------------------------------------------------
     One blue, used for the primary action, the focus ring, and pending
     edits. Anything else that turns blue dilutes all three. */
  --lw-accent: #1f5fb8;         /* 6.20:1 on white */
  --lw-accent-strong: #184a92;  /* hover/active only */
  --lw-accent-tint: #f2f6fd;
  --lw-accent-line: #cddcf2;

  /* -- status ----------------------------------------------------------
     Meaningful states only: settled, needs attention, failed, inert.
     Each value is AA on white, on the canvas, and on its own tint, so a
     badge reads the same wherever it lands. */
  --lw-ok: #0f6b46;
  --lw-ok-tint: #ecfaf3;
  --lw-ok-line: #bfe6d4;
  --lw-warn: #92400e;
  --lw-warn-tint: #fdf7ec;
  --lw-warn-line: #eddcbd;
  --lw-danger: #b42318;
  --lw-danger-tint: #fdf2f1;
  --lw-danger-line: #f2c9c5;
  --lw-neutral: var(--lw-zinc-700);
  --lw-neutral-tint: var(--lw-zinc-50);
  --lw-neutral-line: #e0e0e4;

  /* -- type ------------------------------------------------------------
     Korean sans for everything a person reads as language; mono for
     anything a person compares digit by digit. Both stacks are resolved
     from what the machine already has -- no @font-face, no CDN, so the
     desk renders identically with the network down. */
  --lw-font-sans: system-ui, -apple-system, "Helvetica Neue",
    "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", sans-serif;
  --lw-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  --lw-text-size-micro: 10px;
  --lw-text-size-meta: 11px;
  --lw-text-size-control: 12px;
  --lw-text-size-body: 13px;
  --lw-text-size-title: 15px;
  --lw-text-size-page: 18px;

  --lw-leading-data: 1.2;
  --lw-leading-tight: 1.35;
  --lw-leading-normal: 1.55;

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

  --lw-tracking-tight: -0.01em;
  --lw-tracking-label: 0.045em;

  /* -- space (4px base) ------------------------------------------------ */
  --lw-space-0-5: 2px;
  --lw-space-1: 4px;
  --lw-space-1-5: 6px;
  --lw-space-2: 8px;
  --lw-space-2-5: 10px;
  --lw-space-3: 12px;
  --lw-space-4: 16px;
  --lw-space-5: 20px;
  --lw-space-6: 24px;
  --lw-space-8: 32px;
  --lw-space-10: 40px;

  /* -- radius ---------------------------------------------------------- */
  --lw-radius-xs: 3px;
  --lw-radius-sm: 4px;
  --lw-radius-md: 5px;
  --lw-radius-lg: 7px;
  --lw-radius-xl: 9px;
  --lw-radius-control: var(--lw-radius-md);

  /* -- layering --------------------------------------------------------
     A sticky table has four stacking jobs at once (cell, frozen column,
     header row, their intersection). Naming them here is what stops the
     next z-index from being guessed. */
  --lw-z-cell: 5;
  --lw-z-sticky-col: 10;
  --lw-z-sticky-head: 20;
  --lw-z-sticky-corner: 21;
  --lw-z-topbar: 30;
  --lw-z-overlay: 60;
  --lw-z-tooltip: 70;

  /* -- geometry -------------------------------------------------------- */
  --lw-topbar-height: 48px;
  --lw-nav-width: 248px;
  --lw-page-gutter: 20px;
  --lw-control-height: 28px;
  --lw-control-height-sm: 24px;
  --lw-table-max-height: calc(100vh - 160px);

  /* -- motion ----------------------------------------------------------
     Only state changes animate, and only in color/border. Nothing moves
     position; nothing animates on load. */
  --lw-duration-fast: 90ms;
  --lw-duration: 140ms;
  --lw-ease: cubic-bezier(0.2, 0, 0, 1);

  /* -- focus ----------------------------------------------------------- */
  --lw-focus-ring-width: 2px;
  --lw-focus-ring-offset: 2px;
  --lw-focus-ring-color: var(--lw-accent);
}

/* ======================================================================
   Base defaults -- zero specificity on purpose (see NAMESPACE above).
   ====================================================================== */

:where(*, *::before, *::after) {
  box-sizing: border-box;
}

:where(body) {
  margin: 0;
  background: var(--lw-canvas);
  color: var(--lw-text);
  font-family: var(--lw-font-sans);
  font-size: var(--lw-text-size-body);
  line-height: var(--lw-leading-normal);
  -webkit-font-smoothing: antialiased;
}

/* Korean does not break on spaces alone; without keep-all the browser
   splits 어절 mid-word and a status sentence becomes two half-words. */
:where(body, p, li, td, th, label, legend, caption) {
  word-break: keep-all;
  overflow-wrap: anywhere;
}

:where(input, select, textarea, button) {
  font-family: inherit;
}

:where([hidden]) {
  display: none !important;
}

/* One focus treatment for the whole desk. It is an outline rather than a
   ring drawn with a shadow, so it survives forced-colors mode and never
   gets clipped by a scroll container -- which is where most of this UI
   lives. No rule in this file removes an outline. */
:where(a, button, input, select, textarea, summary, dialog, [tabindex]):focus-visible,
.lw-focus-ring:focus-visible {
  outline: var(--lw-focus-ring-width) solid var(--lw-focus-ring-color);
  outline-offset: var(--lw-focus-ring-offset);
}

/* ======================================================================
   Accessibility utilities
   ====================================================================== */

.lw-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.lw-skip-link {
  position: absolute;
  top: 0;
  left: -9999px;
  z-index: var(--lw-z-tooltip);
  padding: var(--lw-space-2) var(--lw-space-3);
  background: var(--lw-text);
  color: var(--lw-surface);
  border-radius: 0 0 var(--lw-radius-lg) 0;
  font-size: var(--lw-text-size-control);
  text-decoration: none;
}
.lw-skip-link:focus {
  left: 0;
}

/* ======================================================================
   Shell -- topbar + fixed nav + one scrolling work column
   ====================================================================== */

.lw-topbar {
  position: sticky;
  top: 0;
  z-index: var(--lw-z-topbar);
  display: flex;
  align-items: center;
  gap: var(--lw-space-3);
  height: var(--lw-topbar-height);
  padding: 0 var(--lw-page-gutter);
  background: var(--lw-surface);
  border-bottom: 1px solid var(--lw-border);
}

.lw-shell {
  display: grid;
  grid-template-columns: var(--lw-nav-width) minmax(0, 1fr);
  min-height: calc(100vh - var(--lw-topbar-height));
}

.lw-sidenav {
  position: sticky;
  top: var(--lw-topbar-height);
  height: calc(100vh - var(--lw-topbar-height));
  overflow-y: auto;
  padding: var(--lw-space-3) var(--lw-space-4) var(--lw-space-10);
  background: var(--lw-surface);
  border-right: 1px solid var(--lw-border);
}

/* min-width:0 is load-bearing: without it a grid child refuses to shrink
   below its content and the 12-channel table pushes the nav off screen
   instead of scrolling inside its own container. */
.lw-content {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--lw-space-3) var(--lw-page-gutter) var(--lw-space-10);
}

/* --lw-gap is the documented override hook: set it on the element (or on
   any ancestor) to retune one group's rhythm without a new class. */
.lw-stack {
  --lw-gap: var(--lw-space-2);
  display: flex;
  flex-direction: column;
  gap: var(--lw-gap);
}

.lw-cluster {
  --lw-gap: var(--lw-space-2);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--lw-gap);
}

.lw-spacer {
  flex: 1;
}

/* A panel groups related controls. It is a border and a surface -- not a
   card with a shadow -- so ten of them on one page stay quiet. */
.lw-panel {
  background: var(--lw-surface);
  border: 1px solid var(--lw-border);
  border-radius: var(--lw-radius-lg);
}
.lw-panel__header {
  display: flex;
  align-items: center;
  gap: var(--lw-space-2);
  padding: var(--lw-space-2) var(--lw-space-3);
  background: var(--lw-surface-sunken);
  border-bottom: 1px solid var(--lw-border);
  border-radius: var(--lw-radius-lg) var(--lw-radius-lg) 0 0;
}
.lw-panel__body {
  padding: var(--lw-space-3);
}

.lw-divider {
  height: 1px;
  margin: var(--lw-space-3) 0;
  background: var(--lw-border-hair);
  border: 0;
}

/* ======================================================================
   Typography primitives
   ====================================================================== */

.lw-page-title {
  margin: 0;
  font-size: var(--lw-text-size-page);
  font-weight: var(--lw-weight-semibold);
  letter-spacing: var(--lw-tracking-tight);
  line-height: var(--lw-leading-tight);
}

.lw-section-title {
  margin: 0;
  font-size: var(--lw-text-size-title);
  font-weight: var(--lw-weight-semibold);
  line-height: var(--lw-leading-tight);
}

/* Small structural label above a group of controls. No text-transform:
   uppercase does nothing to Hangul and mangles a mixed KO/EN string. */
.lw-eyebrow {
  margin: 0;
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-micro);
  font-weight: var(--lw-weight-semibold);
  letter-spacing: var(--lw-tracking-label);
}

.lw-meta {
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-meta);
}

.lw-prose {
  color: var(--lw-text-body);
  line-height: var(--lw-leading-normal);
  text-wrap: pretty;
}

.lw-mono {
  font-family: var(--lw-font-mono);
  font-variant-numeric: tabular-nums;
}

/* Quantities live in columns and get compared vertically; proportional
   digits make an 11 look wider than a 78 and hide the difference. */
.lw-num {
  font-family: var(--lw-font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--lw-weight-semibold);
  text-align: right;
  white-space: nowrap;
}

.lw-truncate {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ======================================================================
   Controls
   ====================================================================== */

.lw-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--lw-space-1);
  height: var(--lw-control-height);
  padding: 0 var(--lw-space-3);
  background: var(--lw-surface);
  color: var(--lw-text-body);
  border: 1px solid var(--lw-border-strong);
  border-radius: var(--lw-radius-control);
  font-size: var(--lw-text-size-control);
  font-weight: var(--lw-weight-medium);
  line-height: var(--lw-leading-data);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--lw-duration-fast) var(--lw-ease),
    border-color var(--lw-duration-fast) var(--lw-ease),
    color var(--lw-duration-fast) var(--lw-ease);
}
.lw-btn:hover:not(:disabled) {
  background: var(--lw-canvas);
  border-color: var(--lw-mark);
}
.lw-btn:disabled,
.lw-btn[aria-disabled="true"] {
  background: var(--lw-surface-sunken);
  color: var(--lw-text-muted);
  border-color: var(--lw-border);
  cursor: default;
}

.lw-btn--primary {
  background: var(--lw-accent);
  color: var(--lw-text-on-accent);
  border-color: var(--lw-accent);
  font-weight: var(--lw-weight-semibold);
}
.lw-btn--primary:hover:not(:disabled) {
  background: var(--lw-accent-strong);
  border-color: var(--lw-accent-strong);
}

/* Destructive actions are still gated by an explicit confirm elsewhere;
   the button only has to look different from "save". */
.lw-btn--danger {
  color: var(--lw-danger);
  border-color: var(--lw-danger-line);
  background: var(--lw-danger-tint);
}
.lw-btn--danger:hover:not(:disabled) {
  background: var(--lw-surface);
  border-color: var(--lw-danger);
}

.lw-btn--quiet {
  background: transparent;
  border-color: transparent;
  color: var(--lw-text-muted);
}
.lw-btn--quiet:hover:not(:disabled) {
  background: var(--lw-canvas);
  border-color: transparent;
  color: var(--lw-text-body);
}

.lw-btn--sm {
  height: var(--lw-control-height-sm);
  padding: 0 var(--lw-space-2);
  font-size: var(--lw-text-size-meta);
}

.lw-field {
  display: flex;
  flex-direction: column;
  gap: var(--lw-space-1);
}

.lw-label {
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-meta);
  font-weight: var(--lw-weight-medium);
}

.lw-input {
  width: 100%;
  min-height: var(--lw-control-height);
  padding: var(--lw-space-1) var(--lw-space-2);
  background: var(--lw-surface);
  color: var(--lw-text);
  border: 1px solid var(--lw-border-strong);
  border-radius: var(--lw-radius-control);
  font-size: var(--lw-text-size-control);
  transition: border-color var(--lw-duration-fast) var(--lw-ease);
}
.lw-input:hover:not(:disabled) {
  border-color: var(--lw-mark);
}
.lw-input:disabled {
  background: var(--lw-surface-sunken);
  color: var(--lw-text-muted);
  cursor: default;
}
.lw-input[aria-invalid="true"] {
  border-color: var(--lw-danger);
}

/* SKU codes, quantities, pasted lists: typed as data, so shown as data. */
.lw-input--data {
  font-family: var(--lw-font-mono);
  font-variant-numeric: tabular-nums;
}
.lw-input--qty {
  width: 4.5rem;
  text-align: right;
  font-family: var(--lw-font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--lw-weight-semibold);
}

.lw-hint {
  margin: 0;
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-meta);
  line-height: var(--lw-leading-tight);
}
.lw-hint--error {
  color: var(--lw-danger);
}

/* ======================================================================
   Status -- badge, dot, banner
   ====================================================================== */

/* A badge always contains its own words. The tint is a second channel on
   top of the label, never a replacement for it. */
.lw-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--lw-space-1);
  padding: 1px var(--lw-space-1-5);
  background: var(--lw-neutral-tint);
  color: var(--lw-neutral);
  border: 1px solid var(--lw-neutral-line);
  border-radius: var(--lw-radius-xs);
  font-family: var(--lw-font-mono);
  font-size: var(--lw-text-size-micro);
  font-weight: var(--lw-weight-semibold);
  line-height: var(--lw-leading-data);
  white-space: nowrap;
}
.lw-badge--ok {
  background: var(--lw-ok-tint);
  color: var(--lw-ok);
  border-color: var(--lw-ok-line);
}
.lw-badge--warn {
  background: var(--lw-warn-tint);
  color: var(--lw-warn);
  border-color: var(--lw-warn-line);
}
.lw-badge--danger {
  background: var(--lw-danger-tint);
  color: var(--lw-danger);
  border-color: var(--lw-danger-line);
}
.lw-badge--info {
  background: var(--lw-accent-tint);
  color: var(--lw-accent);
  border-color: var(--lw-accent-line);
}
/* The one state that must never be missed in a scan of 100 rows. */
.lw-badge--critical {
  background: var(--lw-danger);
  color: var(--lw-text-on-accent);
  border-color: var(--lw-danger);
  font-weight: var(--lw-weight-bold);
}

/* Shape carries the state as well as hue: circle = settled, diamond =
   attention, square = failed, hollow = nothing observed yet. Pair with a
   text label; the dot alone is a summary, not the answer. */
.lw-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  flex: none;
  background: var(--lw-surface);
  border: 1.5px solid var(--lw-mark);
  border-radius: 50%;
}
.lw-dot--ok {
  background: var(--lw-ok);
  border-color: var(--lw-ok);
}
.lw-dot--warn {
  background: var(--lw-warn);
  border-color: var(--lw-warn);
  border-radius: 1px;
  rotate: 45deg;
}
.lw-dot--danger {
  background: var(--lw-danger);
  border-color: var(--lw-danger);
  border-radius: 1px;
}

.lw-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--lw-space-2);
  padding: var(--lw-space-2) var(--lw-space-3);
  background: var(--lw-surface-sunken);
  color: var(--lw-text-body);
  border: 1px solid var(--lw-border);
  border-radius: var(--lw-radius-lg);
  font-size: var(--lw-text-size-control);
  line-height: var(--lw-leading-tight);
  text-wrap: pretty;
}
.lw-banner--info {
  background: var(--lw-accent-tint);
  border-color: var(--lw-accent-line);
  color: var(--lw-accent);
}
.lw-banner--warn {
  background: var(--lw-warn-tint);
  border-color: var(--lw-warn-line);
  color: var(--lw-warn);
}
.lw-banner--danger {
  background: var(--lw-danger-tint);
  border-color: var(--lw-danger-line);
  color: var(--lw-danger);
}
.lw-banner--ok {
  background: var(--lw-ok-tint);
  border-color: var(--lw-ok-line);
  color: var(--lw-ok);
}

.lw-empty-state {
  padding: var(--lw-space-10) var(--lw-space-5);
  text-align: center;
}
.lw-empty-state__title {
  margin: 0 0 var(--lw-space-1);
  color: var(--lw-text-body);
  font-size: var(--lw-text-size-title);
  font-weight: var(--lw-weight-semibold);
}
.lw-empty-state__body {
  margin: 0;
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-control);
  text-wrap: pretty;
}

/* ======================================================================
   Data table
   ======================================================================
   Twelve channels are wider than any screen. Scrolling right must not
   lose which SKU a row is, and scrolling down must not lose which
   channel a column is: a cell you cannot name is a cell you can write
   the wrong quantity into. So overflow lives on the scroll container --
   position:sticky needs a scroll container to stick to, and putting
   overflow on the table itself silently disables every sticky rule
   below. */

.lw-table-scroll {
  overflow: auto;
  max-height: var(--lw-table-max-height);
  background: var(--lw-surface);
  border: 1px solid var(--lw-border);
  border-radius: var(--lw-radius-lg);
  overscroll-behavior: contain;
}

.lw-table {
  width: max-content;
  min-width: 100%;
  border-collapse: separate;  /* collapse drops sticky cells' borders */
  border-spacing: 0;
}

.lw-table th,
.lw-table td {
  padding: var(--lw-space-1-5) var(--lw-space-2-5);
  border-right: 1px solid var(--lw-border-hair);
  border-bottom: 1px solid var(--lw-border-hair);
  text-align: left;
  vertical-align: middle;
}

/* The left-aligned default above carries one more simple selector than
   the bare .lw-num primitive and would otherwise win, silently undoing
   the right alignment on exactly the cells that need it most. */
.lw-table .lw-num {
  text-align: right;
}

.lw-table thead th {
  position: sticky;
  top: 0;
  z-index: var(--lw-z-sticky-head);
  background: var(--lw-surface-sunken);
  border-bottom: 1px solid var(--lw-border);
  color: var(--lw-text-body);
  font-size: var(--lw-text-size-micro);
  font-weight: var(--lw-weight-semibold);
  white-space: nowrap;
}

.lw-table tbody td {
  background: var(--lw-surface);
}

/* The frozen first column. Keep it display:table-cell -- switching a
   sticky th to flex detaches its height from the row and lets the cells
   underneath show through while scrolling. */
.lw-table .lw-col-frozen {
  position: sticky;
  left: 0;
  z-index: var(--lw-z-sticky-col);
  background: var(--lw-surface);
  border-right: 1px solid var(--lw-border);
}
.lw-table thead .lw-col-frozen {
  z-index: var(--lw-z-sticky-corner);
  background: var(--lw-surface-sunken);
}

.lw-table--numeric td {
  text-align: right;
  font-family: var(--lw-font-mono);
  font-variant-numeric: tabular-nums;
}

.lw-table tbody tr:last-child td,
.lw-table tbody tr:last-child th {
  border-bottom: 0;
}

.lw-cell-selected {
  background: var(--lw-accent-tint);
}
.lw-cell-muted {
  background: var(--lw-surface-sunken);
  color: var(--lw-text-muted);
}

.lw-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--lw-space-1) var(--lw-space-3);
  margin: var(--lw-space-2-5) 0 0;
  color: var(--lw-text-muted);
  font-size: var(--lw-text-size-meta);
}

/* ======================================================================
   Sticky action bar and dialog
   ====================================================================== */

.lw-actionbar {
  position: sticky;
  bottom: 0;
  z-index: var(--lw-z-sticky-head);
  display: flex;
  align-items: center;
  gap: var(--lw-space-3);
  margin-top: var(--lw-space-3);
  padding: var(--lw-space-2) var(--lw-space-3);
  background: var(--lw-surface);
  border: 1px solid var(--lw-border);
  border-radius: var(--lw-radius-lg);
}

/* No elevation: the dialog is separated by a flat scrim and its own
   border, which reads as "this is the only thing you can act on" without
   pretending the page has depth. */
.lw-dialog {
  width: min(560px, calc(100vw - var(--lw-space-10)));
  padding: var(--lw-space-4) var(--lw-space-5);
  background: var(--lw-surface);
  color: var(--lw-text);
  border: 1px solid var(--lw-border-strong);
  border-radius: var(--lw-radius-xl);
}
.lw-dialog::backdrop {
  background: var(--lw-scrim);
}
.lw-dialog__title {
  margin: 0 0 var(--lw-space-2-5);
  font-size: var(--lw-text-size-title);
  font-weight: var(--lw-weight-semibold);
}
.lw-dialog__body {
  max-height: 320px;
  overflow: auto;
  border: 1px solid var(--lw-border-hair);
  border-radius: var(--lw-radius-lg);
}
.lw-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--lw-space-2);
  margin-top: var(--lw-space-3);
}

/* ======================================================================
   Responsive
   ======================================================================
   Desktop-first on purpose: this is a seated tool. Narrow just has to
   stay usable -- the nav stacks above the work column and the table
   keeps its own two-axis scroll rather than reflowing, because a
   reflowed matrix is a matrix whose columns no longer mean anything. */

@media (max-width: 900px) {
  .lw-shell {
    grid-template-columns: minmax(0, 1fr);
  }
  .lw-sidenav {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--lw-border);
  }
  .lw-table-scroll {
    max-height: 70vh;
  }
}

@media (max-width: 600px) {
  :root {
    --lw-page-gutter: 12px;
  }
  .lw-topbar {
    gap: var(--lw-space-2);
  }
  .lw-dialog {
    width: min(560px, calc(100vw - var(--lw-space-4)));
    padding: var(--lw-space-3);
  }
}

/* Coarse pointers get controls that clear the 24px minimum target
   without changing the desktop density. */
@media (pointer: coarse) {
  :root {
    --lw-control-height: 32px;
    --lw-control-height-sm: 28px;
  }
}

/* ======================================================================
   Reduced motion -- zeroing the tokens covers every primitive above; the
   sweep covers anything a page adds on top.
   ====================================================================== */

@media (prefers-reduced-motion: reduce) {
  :root {
    --lw-duration-fast: 0ms;
    --lw-duration: 0ms;
  }
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
