/*
 * Modernist — Ninja Vapes IMS design system.
 *
 * Lifted verbatim from the Claude Design canvas (artifact 814bd500). Tokens,
 * type scale and component classes are exactly as designed — do not retune
 * values here without a design decision behind it.
 *
 * Archivo is a variable font served from three unicode subsets, self-hosted so
 * the application has no external font dependency.
 */

/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/archivo-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/archivo-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;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/archivo-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;
}

:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-divider: color-mix(in srgb, #201e1d 40%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff2ef;
  --color-accent-200: #ffe0d9;
  --color-accent-300: #ffc4b8;
  --color-accent-400: #ff9783;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;
  --color-accent-800: #7c1405;
  --color-accent-900: #4d170e;

  --color-accent-2-100: #fff2ef;
  --color-accent-2-200: #ffe0da;
  --color-accent-2-300: #ffc4b9;
  --color-accent-2-400: #ff9784;
  --color-accent-2-500: #ef6853;
  --color-accent-2-600: #c94b39;
  --color-accent-2-700: #9e3526;
  --color-accent-2-800: #71261b;
  --color-accent-2-900: #471d16;

  --font-heading: "Archivo", system-ui, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Archivo", system-ui, sans-serif;

  --space-1: 4.0px;
  --space-2: 8.0px;
  --space-3: 12.0px;
  --space-4: 16.0px;
  --space-6: 24.0px;
  --space-8: 32.0px;

  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 0px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

.grayscale{filter:grayscale(1) contrast(1.08)}

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
.hr {
  height: 2px; border: 0; margin: var(--space-4) 0;
  background: var(--color-divider);
}

/* — buttons — */
/* display:inline-flex below would otherwise beat [hidden], the same way
   .dialog-backdrop's display:grid does — a hidden button would still show. */
.btn[hidden] { display: none; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* Same treatment for a field that does not apply — a disabled input that
   looks identical to an enabled one just reads as broken. */
.input:disabled, .input[readonly] { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
/* Keep the label on the fill. Global a:hover would otherwise paint it
   accent-700, which disappears on the red button. */
.btn-primary:hover { background: var(--color-accent-600); color: var(--color-bg); }
.btn-primary:active { background: var(--color-accent-700); color: var(--color-bg); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); justify-content: flex-start; text-align: left; }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 2px solid var(--color-divider);
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 2px solid var(--color-divider);
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-divider);
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* ══════════════════════════════════════════════════════════════════════════
   Additions to the canvas system.

   The canvas defines no status colours, but the application needs them for
   scan feedback, stock levels and validation. These are derived from the
   existing ramps so they sit in the same visual family, and are deliberately
   distinct from --color-accent, which is the brand and cannot also mean
   "error".
   ══════════════════════════════════════════════════════════════════════ */

:root {
  --color-success:     #1c7a4f;
  --color-success-100: #e8f5ee;
  --color-success-800: #0e4a2f;

  --color-warning:     #a86808;
  --color-warning-100: #fdf1dc;
  --color-warning-800: #6b4104;

  --color-danger:      #ae1800;   /* --color-accent-700 */
  --color-danger-100:  #fff2ef;   /* --color-accent-100 */
  --color-danger-800:  #7c1405;   /* --color-accent-800 */
}

.tag-success { background: var(--color-success-100); color: var(--color-success-800); }
.tag-warning { background: var(--color-warning-100); color: var(--color-warning-800); }
.tag-danger  { background: var(--color-danger-100);  color: var(--color-danger-800); }

/* Validation state on a form field. */
.field.is-invalid .input { border-color: var(--color-danger); }

.field-error {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 12px;
  color: var(--color-danger);
}

/* An inline message block — sign-in failures, lockout notices, scan warnings. */
.notice {
  display: flex;
  gap: 10px;
  padding: 10px 12px;
  font-size: 13px;
  border-left: 3px solid var(--color-divider);
  background: var(--color-surface);
}

.notice-danger  { border-left-color: var(--color-danger);  background: var(--color-danger-100); }
.notice-warning { border-left-color: var(--color-warning); background: var(--color-warning-100); }
.notice-success { border-left-color: var(--color-success); background: var(--color-success-100); }

.notice svg { flex: none; margin-top: 1px; }

/*
 * Toasts — a save/action result that doesn't need to stay on screen or push
 * page content down, unlike .notice (used for things the user must actually
 * read and act on, e.g. a one-time temporary password). Stacks bottom-right,
 * self-dismisses; see the toast script in design.js.
 */
.toast-stack {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  z-index: 500;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  width: min(360px, calc(100vw - var(--space-4) * 2));
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  font-size: 13px;
  border-left: 3px solid var(--color-divider);
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);
  animation: toast-in 0.18s ease-out;
}

.toast p { margin: 0; flex: 1; }

.toast-warning { border-left-color: var(--color-warning); background: var(--color-warning-100); }
.toast-success { border-left-color: var(--color-success); background: var(--color-success-100); }

.toast-close {
  flex: none;
  border: 0;
  background: none;
  padding: 0;
  margin: -2px -2px 0 0;
  font-size: 16px;
  line-height: 1;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
}
.toast-close:hover { opacity: 1; }

.toast.is-leaving { animation: toast-out 0.15s ease-in forwards; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(8px); }
}

/*
 * Checkbox. The canvas system ships .radio but no checkbox, and a round dot
 * on a multi-select control reads as a radio button. This is .radio's square
 * twin — same size, same states, square to match --radius-*: 0.
 */
.check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 14px;
}

.check input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.check .box {
  width: 16px;
  height: 16px;
  flex: none;
  border: 1.5px solid var(--color-divider);
  background: var(--color-bg);
}

.check:hover .box { border-color: var(--color-accent); }

.check input:checked + .box {
  border-color: var(--color-accent);
  background: var(--color-accent) no-repeat center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23f3f2f2' stroke-width='2.5' stroke-linecap='square'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");
}

.check input:focus-visible + .box {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/*
 * Focus on a text field.
 *
 * The canvas system stacks two treatments on a focused input: the global
 * `:focus-visible` rule paints a 2px solid accent outline, and
 * `.input:focus-visible` pulls that outline to offset 0 while also turning the
 * 1px border accent. The two meet with no gap and read as a single 3px band of
 * solid orange — far heavier than the rest of the system.
 *
 * Same idea, less weight: keep the 1px accent border, and replace the solid
 * outline with a soft accent halo. Focus stays unmistakable without shouting.
 * The transparent outline is kept so Windows High Contrast Mode, which ignores
 * box-shadow, still renders a focus ring.
 */
.input:focus-visible {
  border-color: var(--color-accent);
  outline: 2px solid transparent;
  outline-offset: 0;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}

/*
 * Page-level rules from the canvas's own <helmet> block — part of how the
 * design actually renders, so they belong with the system rather than in a
 * screen stylesheet.
 */
html, body { margin: 0; background: var(--color-bg); }

a { text-decoration: none; }
a:hover { color: var(--color-accent-700); }

input, select, button { font-family: var(--font-body); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--color-neutral-400); }

/* The scanned line flashes accent, then settles. */
@keyframes scanflash {
  0%   { background: var(--color-accent); color: #fff; }
  100% { background: var(--color-surface); color: var(--color-text); }
}

/* A row newly added to a table. */
@keyframes rowin {
  0%   { background: var(--color-accent-200); }
  100% { background: transparent; }
}

/* .dialog-backdrop sets display:grid, which would otherwise beat [hidden]. */
.dialog-backdrop[hidden] { display: none; }

.dialog-actions .btn { min-width: 96px; }

/* Visually hidden, still read by screen readers. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Movement history reversal rows ----------------------------------- */

/* An original row that has been reversed: muted and struck-through. */
tr.move-reversed td {
  opacity: 0.5;
  text-decoration: line-through;
  text-decoration-color: var(--color-neutral-400);
}
tr.move-reversed td a { color: inherit; pointer-events: none; }

/* The compensating row posted by the reversal: subtle left border. */
tr.move-reversal {
  border-left: 2px solid var(--color-neutral-400);
}

/* Delete column: right-aligned, narrow, no wrapping. */
.move-actions {
  text-align: right;
  white-space: nowrap;
  width: 1%;
  padding-right: 12px;
}

/* Inline destructive link-style button for the Delete action. */
.btn-move-delete {
  all: unset;
  cursor: pointer;
  font-size: 11px;
  color: var(--color-accent);
  padding: 2px 4px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.1s;
}
.btn-move-delete:hover { border-bottom-color: var(--color-accent); }
.btn-move-delete:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Danger variant for the confirm button inside the reversal dialog. */
.btn-danger {
  background: var(--color-accent);
  color: #fff;
  border: none;
  padding: 0 20px;
  height: 36px;
  font-size: 14px;
  cursor: pointer;
  letter-spacing: 0.01em;
}
.btn-danger:hover { filter: brightness(0.9); }
.btn-danger:disabled { opacity: 0.5; cursor: not-allowed; }

/* Inline error below the textarea inside the reversal dialog. */
.field-error {
  color: var(--color-accent);
  font-size: 12px;
  margin: 4px 0 0;
}
