/* Hyve Ink — design tokens.
   ---------------------------------------------------------------------------
   One palette, three surfaces: the marketing site (site.css), the order flow and
   the internal admin (below). Component styles change per surface; colour and type
   never do, so the shop's site and the shop's tools cannot drift apart.

   THE PALETTE. Cool paper and near-black ink, with a single blue accent taken from the
   shop's own logo (web/img/hyve-logo.png, the file the shop supplied 2026-09-21). The
   mark is a bevelled blue, so it is a range rather than one value: its median is #1B77D9,
   which is --brand, and its commonest shade — the body of the bevel — is #106CD0, which
   is --accent-fill. Every blue here is inside the logo's own range or a step darker. The accent is used once per screen rather than as a theme,
   so it reads as a brand mark rather than as decoration. Everything else is neutral,
   which is what lets one accent carry the whole page.

   The accent is NOT the brand blue itself. #1B77D9 sits in the middle of the luminance
   range, where white text scores 4.48:1 on it and black scores 4.69:1 — white just
   misses. So --brand is for the logo and for decoration, and --accent-fill is a shade
   darker, where white clears 4.5:1. Every pairing in this file was computed, and the
   numbers are in the comments beside the values that depend on them.

   THREE THEME STATES, not two. An explicit choice stamps data-theme on <html>; the
   default setting stamps nothing and only prefers-color-scheme separates light from
   dark. So: the bare :root block is the complete light palette, the media query
   redefines tokens for an un-stamped dark OS, and the [data-theme] blocks let a
   deliberate choice win in both directions. Never give a colour its only definition
   inside a media query — that is how a page ends up with one theme's text on the
   other theme's background. */

:root {
  color-scheme: light;

  /* Surfaces, cool rather than warm. They were a warm cream, which was right when the
     accent was amber and is wrong beside the brand azure — cream and blue read as two
     palettes sharing a page rather than one.
     The gaps between them are deliberately small but never invisible: panel used to sit
     1.03:1 against bg, which is below the threshold where an edge reads as an edge, so
     every card on the light page looked like a hole rather than a surface.
     Darkened again 2026-09-30 at the shop's ask ("the boxes need to be a bit darker"):
     bg, panel-2 and both lines one step down, so a white card and its border read at a
     glance on a bright screen. */
  --bg:        #EDEFF3;
  --panel:     #FFFFFF;
  --panel-2:   #E1E5EB;
  --ink:       #14161A;
  --ink-soft:  #3A3E46;
  --muted:     #5C616B;
  /* Text for a control that is there but not yet available — a wizard step you cannot
     reach. It used to be --muted at opacity .45, which is 1.99:1 here and 2.19:1 in the
     dark theme. A colour instead: 4.82:1 on --panel, still visibly quieter than --muted
     (6.22:1), and the step's number loses its filled circle so colour is not the only
     cue. */
  --muted-off: #686C75;  /* 4.57:1 on the darker --bg, 5.26:1 on --panel (2026-09-30). */
  --line:      #C2C8D1;
  --line-soft: #D8DCE3;
  /* PAPER: the ground a garment photo sits on, in BOTH themes. SanMar shoots every
     garment on pure white, and a white rectangle inside a dark stage is a hole; the
     stage, the preview thumbnails and the cart picture are paper instead, so the photo's
     ground and the surface are one. Defined once, here, and never overridden by the dark
     blocks — that is the point of it. (2026-09-22, the shop: "make it look nice".) */
  --paper:     #FFFFFF;

  /* THE BRAND COLOUR. The median of the shop's logo file (see the header). It is used
     for decoration, NEVER as a background with white text on it: white on it is 4.48:1,
     a hair under the 4.5:1 text needs. */
  --brand:       #1B77D9;

  /* The one accent, a shade down from the brand so that white text on it clears 4.5:1.
     -fill is for blocks of colour, -ink for text on a light ground. */
  --accent:      #0C5FBF;
  --accent-fill: #106CD0;
  --accent-ink:  #0B57B0;
  --accent-soft: #E8F1FC;
  /* Text and icons drawn ON a block of accent. --accent-fill is the same value in both
     themes, so one ink works everywhere and no media query has to correct it — which is
     how white-on-amber at 1.76:1 got shipped in three places. White on this fill is
     5.15:1, which is why the fill is the logo's deeper shade and not its median. */
  --on-accent:   #FFFFFF;
  /* The focus ring, darker than the fill so it stays a 3:1 indicator on a tinted
     section as well as on paper. */
  --focus:       #0B57B0;

  /* The inverted call-to-action. In light this is near-black on paper; in dark, reusing
     --ink as a background turned it into a full-width white slab. */
  --cta-bg:   #16161A;
  --cta-ink:  #FAF9F6;
  --cta-edge: rgba(250, 249, 246, .30);

  /* States. Named for what they mean, not what colour they are. */
  --warn-bg:  #FFF6E0; --warn-line:  #E5C065; --warn-ink:  #6B4C05;
  /* "We quote this by hand" moved off blue when blue became the brand. A tinted blue
     panel beside a blue button reads as the same thing said twice, and this state means
     something quite different from "press me". */
  --quote-bg: #F0EDFA; --quote-line: #B0A3DC; --quote-ink: #43307F;
  --stop-bg:  #FDECEC; --stop-line:  #DD9999; --stop-ink:  #8C1F1F;
  --good-bg:  #E8F5EE; --good-line:  #86BFA0; --good-ink:  #14532D;

  --display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --body:    'Manrope', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --r-sm: 6px;  --r-md: 10px;  --r-lg: 16px;  --r-xl: 24px;
  /* Tinted toward the paper they fall on — now cool, previously warm. A shadow of the
     wrong temperature reads as dirt rather than as depth. */
  --shadow-sm: 0 1px 2px rgba(18, 24, 38, .12);
  --shadow-md: 0 2px 6px rgba(18, 24, 38, .07), 0 14px 30px -18px rgba(18, 24, 38, .30);
  --shadow-lg: 0 4px 12px rgba(18, 24, 38, .08), 0 28px 60px -30px rgba(18, 24, 38, .42);
  /* For drop-shadow() on the hero garment, which is a filter rather than a box-shadow. */
  --shadow-art: rgba(18, 24, 38, .20);

  /* Body copy sizes. Four steps, because the page previously ran 14 / 14.5 / 15 / 15.5 /
     16.5 / 17 / 17.5 for three actual roles — differences nobody perceives individually
     and which collectively stop a page feeling like it was designed. */
  --fs-xs: 13.5px;
  --fs-sm: 15px;
  --fs-md: 17px;
  --fs-lg: 19px;

  --page: 1180px;

  /* Stacking layers, lowest first. Every z-index on the site names one of these rather
     than picking a number: two stylesheets each choosing "high enough" is how the header
     (50) ended up over the design tool's dialogs (40), hiding their titles. A new layer
     goes in this list, in order, not in a rule somewhere. */
  --layer-raised: 2;    /* floats over its own section: the stage controls and notices */
  --layer-sticky: 50;   /* stays in view while the page scrolls: the site header, the wizard's Next bar */
  --layer-dialog: 100;  /* modal: a dialog and its backdrop cover everything, the header included */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:        #0F1116;
    --panel:     #171A21;
    --panel-2:   #1F232C;
    --ink:       #E9ECF1;
    --ink-soft:  #C2C7D0;
    --muted:     #8E95A3;
    --muted-off: #7F8593; /* 4.71:1 on --panel. See the light block. */
    --line:      #2A2F3A;
    --line-soft: #1F232C;

    --brand:       #1B77D9;
    /* --accent does double duty as a border AND as the hover background under white
       text, and on a dark ground those pull opposite ways: white needs it dark, a
       visible border needs it light. The window between the two is narrow and this value
       is inside it — white 5.15:1, border on panel 3.38:1. Do not lighten it without
       re-checking the first number. */
    --accent:      #106CD0;
    --accent-fill: #106CD0;
    --accent-ink:  #6FB0F5;
    --accent-soft: #12233A;
    --on-accent:   #FFFFFF;
    --focus:       #6FB0F5;

    --cta-bg:   #1C1C22;
    --cta-ink:  #ECEAE6;
    --cta-edge: rgba(236, 234, 230, .22);

    --warn-bg:  #332810; --warn-line:  #7D6420; --warn-ink:  #F3D98A;
    --quote-bg: #1E1A33; --quote-line: #4E4287; --quote-ink: #C4B7F0;
    --stop-bg:  #341A1A; --stop-line:  #7D3A3A; --stop-ink:  #F0B3B3;
    --good-bg:  #12301F; --good-line:  #2F6B48; --good-ink:  #9FDCBB;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow-md: 0 2px 6px rgba(0, 0, 0, .5), 0 12px 28px -18px rgba(0, 0, 0, .8);
    --shadow-lg: 0 4px 12px rgba(0, 0, 0, .55), 0 28px 60px -30px rgba(0, 0, 0, .9);
    --shadow-art: rgba(0, 0, 0, .65);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:        #0F1116;
  --panel:     #171A21;
  --panel-2:   #1F232C;
  --ink:       #E9ECF1;
  --ink-soft:  #C2C7D0;
  --muted:     #8E95A3;
  --muted-off: #7F8593;
  --line:      #2A2F3A;
  --line-soft: #1F232C;

  --brand:       #1B77D9;
  /* See the media-query block above for why --accent is this exact value and not a
     lighter one. The two dark blocks must stay identical. */
  --accent:      #106CD0;
  --accent-fill: #106CD0;
  --accent-ink:  #6FB0F5;
  --accent-soft: #12233A;
  --on-accent:   #FFFFFF;
  --focus:       #6FB0F5;

  --cta-bg:   #1C1C22;
  --cta-ink:  #ECEAE6;
  --cta-edge: rgba(236, 234, 230, .22);

  --warn-bg:  #332810; --warn-line:  #7D6420; --warn-ink:  #F3D98A;
  --quote-bg: #1E1A33; --quote-line: #4E4287; --quote-ink: #C4B7F0;
  --stop-bg:  #341A1A; --stop-line:  #7D3A3A; --stop-ink:  #F0B3B3;
  --good-bg:  #12301F; --good-line:  #2F6B48; --good-ink:  #9FDCBB;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, .5), 0 12px 28px -18px rgba(0, 0, 0, .8);
  --shadow-lg: 0 4px 12px rgba(0, 0, 0, .55), 0 28px 60px -30px rgba(0, 0, 0, .9);
  --shadow-art: rgba(0, 0, 0, .65);
}

/* One focus ring for every surface. This lived in site.css scoped to .site, which left
   the entire order flow — five steps, a 60-row garment list, every chip — on the browser
   default. It is unscoped on purpose. */
:focus-visible {
  outline: 2.5px solid var(--focus);
  outline-offset: 3px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ===================================================================== wizard */

.wz * { box-sizing: border-box; }
.wz {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 16px/1.55 var(--body);
}
.wz input, .wz select, .wz button { font: inherit; color: inherit; }

.wz-head {
  padding: 14px 22px; border-bottom: 1px solid var(--line); background: var(--panel);
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
}
.wz-head h1 { font-size: 17px; margin: 0; letter-spacing: .01em; }
.wz-head .wz-mark { display: block; flex-shrink: 0; }
.wz-head .wz-mark img { display: block; width: 26px; height: 24px; }
.wz-head .sub { color: var(--muted); font-size: 13px; }
.wz-head .spacer { flex: 1; }
.wz-head a { color: var(--muted); font-size: 13px; }

.wz-banner {
  padding: 10px 22px; font-size: 13px; font-weight: 600;
  background: var(--warn-bg); color: var(--warn-ink); border-bottom: 1px solid var(--warn-line);
}
.wz-banner span { font-weight: 400; }

/* Step rail ------------------------------------------------------------ */

.wz .steps {
  display: flex; gap: 0; padding: 0 22px; background: var(--panel);
  border-bottom: 1px solid var(--line); overflow-x: auto;
}
.wz .steps li { list-style: none; }
.wz .steps button {
  border: 0; background: none; cursor: pointer; padding: 11px 0; margin-right: 26px;
  color: var(--muted); font-size: 13.5px; white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.wz .steps button[disabled] { cursor: default; color: var(--muted-off); }
.wz .steps button[disabled] .n {
  background: none; color: var(--muted-off); box-shadow: inset 0 0 0 1px var(--muted-off);
}
.wz .steps button.on { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }
.wz .steps button.done { color: var(--ink); }
.wz .steps .n {
  display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%;
  background: var(--line); color: var(--ink); font-size: 11.5px; margin-right: 7px;
  font-variant-numeric: tabular-nums;
}
.wz .steps button.on .n { background: var(--accent-fill); color: var(--on-accent); }

/* Layout --------------------------------------------------------------- */

.wz-main {
  display: grid; grid-template-columns: 1fr minmax(240px, 300px);
  gap: 26px; align-items: start; padding: 24px 22px 80px;
  max-width: var(--page); margin-inline: auto;
}
@media (max-width: 880px) { .wz-main { grid-template-columns: 1fr; } }

.wz .stage { min-width: 0; }
.wz .stage h2 { font-size: 22px; margin: 0 0 4px; letter-spacing: -.01em; }
/* Breadcrumb out of a drill-in, so it is obvious you are inside a step, not on a new one. */
.wz button.crumb {
  background: none; border: 0; padding: 0; margin: 0 0 12px; cursor: pointer;
  color: var(--muted); font-size: 13.5px;
}
.wz button.crumb:hover { color: var(--ink); text-decoration: underline; }
.wz .stage .lede { color: var(--muted); margin: 0 0 20px; font-size: 14.5px; }

.wz .rail {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px 16px; font-size: 13.5px; position: sticky; top: 18px;
}
.wz .rail h3 {
  margin: 0 0 10px; font-size: 11px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted);
}
.wz .rail .empty { color: var(--muted); }
.wz .rail dl { margin: 0; display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; }
.wz .rail dt { color: var(--muted); }
.wz .rail dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.wz .rail .grp { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 10px; }
.wz .rail .grp:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.wz .rail b { font-weight: 600; }

/* Cards, fields -------------------------------------------------------- */

.wz .panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 16px 18px; margin-bottom: 16px;
}
.wz .panel > h3 {
  margin: 0 0 12px; font-size: 12px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted);
}
.wz .field { margin-bottom: 14px; }
.wz .field > label, .wz .lbl {
  display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px;
}
.wz input[type=text], .wz input[type=number], .wz input[type=search],
.wz input[type=email], .wz input[type=tel], .wz select {
  width: 100%; padding: 9px 11px; border: 1px solid var(--line);
  border-radius: 7px; background: var(--bg);
}
.wz input[type=number] { font-family: var(--mono); }
.wz .two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.wz .three { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
/* Scoped to .wz so it matches the rules it overrides. It was written as ".two, .three",
   specificity 0-1-0, against ".wz .two" at 0-2-0 — and a media query adds no specificity
   of its own, so this had never applied to anything. Width/Height and Phone/Organization
   sat side by side at 375px with about 141px each. */
@media (max-width: 560px) {
  .wz .two, .wz .three { grid-template-columns: 1fr; }
}

/* The quote screen is the thing this product exists to produce, and it had no
   small-screen layout at all: four columns at any width, with the description squeezed
   to roughly 100px on a phone. Below 560px the money moves under the description rather
   than fighting it for room. */
@media (max-width: 560px) {
  .wz .quote .items li,
  .wz .quote .sum {
    grid-template-columns: 26px 1fr;
    row-gap: 4px;
  }
  .wz .quote .items li .ea,
  .wz .quote .sum .ea { grid-column: 2; text-align: left; }
  .wz .quote .items li .amt,
  .wz .quote .sum .amt { grid-column: 2; text-align: left; }
}
.wz .hint { font-size: 12.5px; color: var(--muted); margin: 6px 0 0; }
.wz .hint.alert { color: var(--stop-ink); }
.wz .req { color: var(--stop-ink); }

/* Checkout ------------------------------------------------------------- */

/* What is owed, restated above the form. Styled like the quote total it repeats — the
   figure is the same string the server sent, and looking different would imply it is a
   different number. */
.wz .paysum {
  display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 2px 14px;
  padding: 15px 18px; margin-bottom: 18px;
  background: var(--panel); border: 1px solid var(--line);
  border-top: 2px solid var(--ink); border-radius: 10px;
}
.wz .paysum .k { font-weight: 600; font-size: 16px; }
.wz .paysum .v {
  font-family: var(--mono); font-size: 21px; font-weight: 600;
  text-align: right; letter-spacing: -.01em;
}
.wz .paysum .n { grid-column: 1 / -1; color: var(--muted); font-size: 12.5px; }

/* The non-returnable acknowledgement. Deliberately not a line of small print beside a
   bare checkbox: it is the one thing on this screen the customer is agreeing TO, so it
   gets a box of its own and changes colour once ticked. */
.wz .ack {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 16px; margin: 2px 0 0;
  border: 1px solid var(--line); border-radius: 10px; background: var(--bg);
  cursor: pointer; font-size: 14px; line-height: 1.5;
}
.wz .ack input { width: 20px; height: 20px; margin: 1px 0 0; flex: none; cursor: pointer; }
.wz .ack:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.wz .verdict[tabindex] { outline-offset: 3px; }

/* The wizard's way out. Deliberately quiet — it is a safety net, not a call to
   action — but always present, because the only alternative was browser Back. */
.wz-foot {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline;
  max-width: 1180px; margin: 0 auto; padding: 22px 22px 40px;
  border-top: 1px solid var(--line); color: var(--muted); font-size: 13px;
}
.wz-foot a { color: var(--accent-ink); }
.wz-foot .sep { opacity: .5; }

/* Present to assistive technology, absent to everyone else. Not display:none, which
   would hide it from screen readers too and defeat the point. */
.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;
}

/* Quote request ---------------------------------------------------------- */

.wz textarea {
  width: 100%; padding: 9px 11px; border: 1px solid var(--line);
  border-radius: 7px; background: var(--bg); resize: vertical; min-height: 76px;
  font: inherit; color: inherit;
}
.wz .ask-h { font-size: 17px; margin: 24px 0 12px; letter-spacing: -.01em; }
.wz .verdict p a { color: inherit; font-weight: 600; }

/* Buttons -------------------------------------------------------------- */

.wz button.go, .wz button.ghost {
  padding: 11px 22px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 15px;
}
.wz button.go { background: var(--accent-fill); color: var(--on-accent); border: 0; }
.wz button.go[disabled] { opacity: .4; cursor: not-allowed; }
.wz button.ghost { background: none; border: 1px solid var(--line); color: var(--ink); }
.wz button.ghost:hover { border-color: var(--accent); }
.wz button.go.small, .wz button.ghost.small { padding: 6px 12px; font-size: 13px; margin: 0 6px 0 0; }

/* "Do you have a vector version of this?" after a PNG or JPEG. A question, not a stop. */
.wz .vector-ask {
  margin: 10px 0 0; padding: 10px 12px; border: 1px solid var(--accent); border-radius: 9px;
  background: var(--accent-soft); font-size: 13px; line-height: 1.5;
}
.wz .vector-ask[hidden] { display: none; }
.wz .vector-ask strong { display: block; }
.wz .vector-ask p { margin: 4px 0 8px; }
/* Sticks to the bottom of the screen. The garment browser can run to 60 rows, which
   would otherwise leave "Next" far below the fold and push people into the step rail. */
.wz .nav {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  position: sticky; bottom: 0; z-index: var(--layer-sticky);
  margin-top: 22px; padding: 13px 0;
  background: var(--bg); border-top: 1px solid var(--line);
}
.wz .nav .spacer { flex: 1; }
.wz .nav .why { color: var(--muted); font-size: 13px; }

/* Garment browser ------------------------------------------------------ */

.wz .cats { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 14px; }
.wz .cats button {
  padding: 6px 13px; border-radius: 999px; cursor: pointer; font-size: 13.5px;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
}
.wz .cats button.on { border-color: var(--accent-fill); background: var(--accent-fill); color: var(--on-accent); }

.wz .results { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--panel); }
.wz .results .row {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 12px 16px; border: 0; border-top: 1px solid var(--line);
  background: none; cursor: pointer; color: inherit;
}
.wz .results .row:first-child { border-top: 0; }
.wz .results .row:hover { background: var(--bg); }
.wz .results .row .nm { flex: 1; min-width: 0; }
.wz .results .row .nm b { display: block; font-weight: 600; font-size: 14.5px; }
.wz .results .row .nm span { color: var(--muted); font-size: 12.5px; }
.wz .results .row .px { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 13px; white-space: nowrap; }
.wz .results .none { padding: 22px 16px; color: var(--muted); text-align: center; }
.wz .count { font-size: 12.5px; color: var(--muted); margin: 10px 0 0; }

/* Sizes ---------------------------------------------------------------- */

.wz .sizegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 10px; }
.wz .sizegrid div { display: grid; gap: 4px; }
.wz .sizegrid span { font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
/* The stock check (web/stock.js): a size SanMar has none of is greyed and says so; a
   quantity above what is left says how many are. */
.wz .sizegrid input:disabled { color: var(--muted-off); cursor: not-allowed; }
.wz .sizegrid .blocked label, .wz .sizegrid .stock { color: var(--muted-off); }
.wz .sizegrid .stock.over { color: var(--stop-ink); }
.wz .sizegrid .stock:empty { display: none; }

/* Chips / toggles ------------------------------------------------------ */

.wz .chips { display: flex; flex-wrap: wrap; gap: 8px; }
.wz .chips label {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px;
  border: 1px solid var(--line); border-radius: 999px; cursor: pointer;
  background: var(--panel); font-size: 13.5px;
}
.wz .chips label:has(input:checked) { border-color: var(--accent); background: var(--bg); }
.wz .chips input { margin: 0; }
.wz .swatch { width: 15px; height: 15px; border-radius: 50%; border: 1px solid var(--line); }

/* Line-item list of things added so far -------------------------------- */

.wz .added { margin: 0 0 16px; padding: 0; list-style: none; }
.wz .added li {
  display: flex; align-items: center; gap: 12px; padding: 11px 14px;
  border: 1px solid var(--line); border-radius: 9px; margin-bottom: 9px; background: var(--panel);
}
.wz .added li .nm { flex: 1; min-width: 0; }
.wz .added li .nm b { display: block; font-weight: 600; font-size: 14.5px; }
.wz .added li .nm span { color: var(--muted); font-size: 12.5px; }
.wz .added li button {
  border: 0; background: none; cursor: pointer; color: var(--muted);
  font-size: 13px; text-decoration: underline; padding: 10px 8px;
}
.wz .added li button:hover { color: var(--stop-ink); }

/* Placement matrix ----------------------------------------------------- */

.wz .place { border: 1px solid var(--line); border-radius: 10px; background: var(--panel); margin-bottom: 14px; }
.wz .place > header { padding: 12px 16px; border-bottom: 1px solid var(--line); }
.wz .place > header b { font-size: 14.5px; }
.wz .place > header span { color: var(--muted); font-size: 12.5px; display: block; }
.wz .place .body { padding: 6px 16px 14px; }
.wz .place .line { padding: 10px 0; border-top: 1px solid var(--line); }
.wz .place .line:first-child { border-top: 0; }
.wz .place .line > .lbl { margin-bottom: 7px; color: var(--ink); font-size: 13.5px; font-weight: 600; }

/* Quote ---------------------------------------------------------------- */

.wz .quote { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.wz .quote .items { margin: 0; padding: 0; list-style: none; }
.wz .quote .items li {
  display: grid; grid-template-columns: 26px 1fr auto auto;
  gap: 14px; align-items: baseline; padding: 13px 18px; border-top: 1px solid var(--line);
}
.wz .quote .items li:first-child { border-top: 0; }
.wz .quote .items li.checked .desc { opacity: .5; text-decoration: line-through; }
/* 20px with negative-margin padding: a 32px hit area for Amanda's thumb on a tablet,
   without the box itself growing and shunting the grid column. */
.wz .quote .items input {
  width: 20px; height: 20px; margin: -6px; padding: 6px;
  box-sizing: content-box; cursor: pointer;
}
.wz .quote .desc b { display: block; font-weight: 500; font-size: 15px; }
.wz .quote .desc span { color: var(--muted); font-size: 12.5px; }
.wz .quote .ea { color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wz .quote .amt { font-family: var(--mono); font-size: 15px; text-align: right; white-space: nowrap; }
.wz .quote .sum {
  display: grid; grid-template-columns: 26px 1fr auto auto; gap: 14px; align-items: baseline;
  padding: 16px 18px; border-top: 2px solid var(--ink); background: var(--bg);
}
.wz .quote .sum .desc b { font-weight: 700; font-size: 16px; }
.wz .quote .sum .amt { font-size: 21px; font-weight: 600; letter-spacing: -.01em; }
.wz .quote .sum .ea { font-size: 15px; color: var(--ink); }
.wz .quote .sum.tax { border-top: 1px solid var(--line); padding-block: 10px; }
.wz .quote .sum.tax .desc b { font-weight: 500; font-size: 14.5px; }
.wz .quote .sum.tax .amt { font-size: 15px; font-weight: 400; }

.wz .verdict { border-radius: 10px; padding: 18px 20px; border: 1px solid; margin-bottom: 18px; }
.wz .verdict h2 { margin: 0 0 6px; font-size: 19px; }
.wz .verdict p { margin: 0 0 6px; }
.wz .verdict.quote-v { background: var(--quote-bg); border-color: var(--quote-line); color: var(--quote-ink); }
.wz .verdict.stop { background: var(--stop-bg); border-color: var(--stop-line); color: var(--stop-ink); }
.wz .verdict ul { margin: 10px 0 0; padding-left: 20px; }
.wz .verdict li { margin-bottom: 6px; }
.wz .verdict a { color: inherit; font-weight: 600; }

.wz .notes { margin: 18px 0 0; font-size: 12.5px; color: var(--muted); }
.wz .notes li { margin-bottom: 5px; }
.wz .notes li.alert { color: var(--stop-ink); }

/* Print ---------------------------------------------------------------- */

@media print {
  /* Scoped to .wz, not :root. These pages share a stylesheet with the marketing site, and
     as a global override they also stripped the brand off a printed pricing page. Custom
     properties inherit, so putting them on the wizard body reaches everything inside it. */
  .wz {
    --bg: #fff; --panel: #fff; --ink: #000; --muted: #444; --line: #bbb; --accent: #000;
    --accent-fill: #fff; --on-accent: #000; --focus: #000;
    --warn-bg: #fff; --warn-ink: #000; --warn-line: #bbb;
  }
  .wz-head .spacer, .wz-head a, .wz .steps, .wz .rail, .wz .nav, .wz .no-print { display: none !important; }
  .wz-main { display: block; padding: 0; max-width: none; margin-inline: 0; }
  .wz .quote, .wz .panel { border-color: #bbb; break-inside: avoid; }
  .wz .quote .items input { -webkit-appearance: none; appearance: none; border: 1px solid #000; }
  .wz-banner { border: 1px solid #000; }
  .wz { font-size: 12px; }
}

/* ===================================================== admin (price editor) */

/* The sentence at the top of each screen stating the rule people get wrong. It is
   deliberately louder than a hint — on the print-prices screen it is worth more than
   any validation rule, because it is placed exactly where the mistake gets made. */
.wz .note-rule {
  background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn-line);
  border-radius: 8px; padding: 12px 15px; margin: 0 0 20px; font-size: 14px; line-height: 1.5;
}

.wz .worked {
  background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: 6px; padding: 12px 15px; margin: 14px 0 0; font-size: 14px; line-height: 1.5;
}
.wz .worked b { font-weight: 600; }

.wz .scrollx { overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.wz table.grid { width: 100%; border-collapse: collapse; font-size: 14px; }
.wz table.grid th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); font-weight: 600; padding: 11px 12px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.wz table.grid th.num { text-align: right; }
.wz table.grid td { padding: 7px 12px; border-top: 1px solid var(--line); }
.wz table.grid th.rowhead {
  border-top: 1px solid var(--line); border-bottom: 0; color: var(--ink);
  font-family: var(--mono); font-size: 12.5px; text-transform: none; letter-spacing: 0;
}
.wz table.grid td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.wz table.grid input[type=text], .wz table.grid input[type=number] {
  width: 88px; padding: 6px 8px; text-align: right;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
/* An empty cell means "we price this by hand", which is a real decision — show it as
   one rather than as a box somebody forgot to fill in. */
.wz table.grid input.blank { border-style: dashed; color: var(--muted); }
.wz table.grid select { width: auto; min-width: 96px; }

.wz label.radio {
  display: flex; align-items: baseline; gap: 9px; padding: 9px 0; font-size: 14.5px;
  color: var(--ink); cursor: pointer;
}
.wz label.radio span { color: var(--muted); }

.wz .rail .problem {
  display: grid; gap: 3px; padding: 11px 13px; border-radius: 7px; margin: 10px 0;
  font-size: 12.5px; line-height: 1.45; border: 1px solid;
}
.wz .rail .problem b {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; font-weight: 700;
}
.wz .rail .problem.error { background: var(--stop-bg); border-color: var(--stop-line); color: var(--stop-ink); }
.wz .rail .problem.confirm { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-ink); }
.wz .rail button.go, .wz .rail button.ghost { width: 100%; margin-top: 10px; }

/* ===================================================== proof preview & glyphs */

/* The design step becomes two columns once there is room: controls on the left, the
   preview on the right, sticky so it stays in view while the form is filled in. Below
   that width it stacks with the preview FIRST, because on a phone the picture is the
   thing worth seeing without scrolling. */

/* Ordered with `order`, not grid-template-areas. The panel carries FOUR children — the
   heading and the remove button as well as the controls and the preview — and named areas
   only placed two of them, so the other two auto-placed into whatever cell was left. That
   put the controls in the 300px rail on desktop and the heading BELOW its own content on
   mobile. `order` has no such trap. */
.wz .design-panel { display: grid; gap: 18px 26px; }
.wz .design-panel > h3     { order: 0; }
.wz .proof-host            { order: 1; }
.wz .design-controls       { order: 2; }
.wz .design-panel > button { order: 3; justify-self: start; }

@media (min-width: 900px) {
  .wz .design-panel { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; }
  .wz .design-panel > h3,
  .wz .design-panel > button { grid-column: 1 / -1; }
  /* Controls left, preview right — and the preview stays put while the form is filled in. */
  .wz .design-controls { order: 1; }
  .wz .proof-host { order: 2; position: sticky; top: 16px; }
}
.wz .design-controls { display: grid; gap: 0; align-content: start; min-width: 0; }

.wz .proof {
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--bg); overflow: hidden;
}
.wz .proof-stage {
  padding: 18px; display: grid; place-items: center;
  /* A faint grid, the way a cutting mat reads — it gives the drawing a sense of scale
     without competing with it. */
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 16px 16px;
}
.wz .proof-stage svg { width: 100%; max-width: 260px; height: auto; display: block; border-radius: 8px; }
/* Holds the stage open for the moment before the mirror answers and the proof is drawn. */
.wz .proof-stage:empty { min-height: 280px; }

/* Proof-preview ink ---------------------------------------------------------
   Unscoped, because the same renderer draws the hero on the marketing page.

   These four values are NOT theme tokens and must never be wired to one. They resolve
   from `data-ground`, which mockup.js sets from the GARMENT's lightness: ink drawn on a
   black tee has to be light whether the page is in light mode or dark. The previous code
   used --accent and --stop-ink here, so on the two colours a print shop sells most —
   black and navy — the print-area boundary was low-contrast and the oversize warning was
   dark red on near-black, i.e. invisible in the exact state it exists to announce. */
.mockup-svg {
  --on-garment:       rgba(0, 0, 0, .55);
  --edge-on-garment:  rgba(0, 0, 0, .45);
  --alarm-on-garment: #A11B14;
  --ghost-on-garment: rgba(0, 0, 0, .07);
}
.mockup-svg[data-ground="dark"] {
  --on-garment:       rgba(255, 255, 255, .72);
  --edge-on-garment:  rgba(255, 255, 255, .55);
  --alarm-on-garment: #FF9E9E;
  --ghost-on-garment: rgba(255, 255, 255, .12);
}

.mockup-svg text { font-family: var(--body); }

.mockup-svg .area {
  fill: none; stroke: var(--edge-on-garment);
  stroke-width: .09; stroke-dasharray: .4 .34; opacity: .85;
}
.mockup-svg .area.over { stroke: var(--alarm-on-garment); opacity: 1; stroke-width: .12; }

.mockup-svg .dim { fill: none; stroke: var(--on-garment); stroke-width: .06; stroke-linecap: round; }
.mockup-svg .dim text { stroke: none; fill: var(--on-garment); font-weight: 600; }
.mockup-svg .dim.over { stroke: var(--alarm-on-garment); }
.mockup-svg .dim.over text { fill: var(--alarm-on-garment); }

.mockup-svg .ghost {
  fill: var(--ghost-on-garment); stroke: var(--edge-on-garment);
  stroke-width: .07; stroke-dasharray: .3 .24;
}
.mockup-svg .ghost-label,
.mockup-svg .byhand { fill: var(--on-garment); }

.wz .proof-note {
  margin: 0; padding: 13px 16px; font-size: 12.5px; line-height: 1.5;
  color: var(--muted); border-top: 1px solid var(--line); background: var(--panel);
}
.wz .proof-note.over { color: var(--stop-ink); background: var(--stop-bg); border-top-color: var(--stop-line); }

/* Browse-list silhouette. Sized to the row, coloured by inheritance so it is correct in
   both themes without a second rule. */
/* SanMar's thumbnail of the style: a garment on a white ground, so the box is white in
   both themes and rounded so it reads as a picture rather than a hole. */
.wz .glyph {
  width: 36px; height: 44px; flex-shrink: 0; display: grid; place-items: center;
  border-radius: 6px; overflow: hidden;
}
.wz .glyph:has(img) { background: #fff; }
.wz .glyph img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* The wizard header borrows the site's theme toggle. */
.wz-head .theme-btn {
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: transparent; color: var(--muted); cursor: pointer;
}
.wz-head .theme-btn:hover { color: var(--ink); border-color: var(--accent); }
.wz-head .theme-btn svg { width: 15px; height: 15px; }
.wz-head h1 { color: var(--ink); }
:root:not([data-theme="dark"]) .wz-head .theme-btn .moon { display: none; }
:root[data-theme="dark"] .wz-head .theme-btn .sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .wz-head .theme-btn .sun { display: none; }
  :root:not([data-theme]) .wz-head .theme-btn .moon { display: block; }
}

.wz .verdict.ok { background: var(--quote-bg); border-color: var(--quote-line); color: var(--quote-ink); }
.wz .verdict.warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-ink); }
.wz .verdict h3 { margin: 0 0 6px; font-size: 16px; }

/* The warnings check in front of a save: one .ack box per warning (see checkout's
   non-returnable tick above for the box itself), and the commit button beneath. */
.wz fieldset.acks { border: 0; padding: 0; margin: 18px 0 0; display: grid; gap: 10px; min-width: 0; }
.wz fieldset.acks legend { padding: 0; margin-bottom: 10px; font-weight: 600; font-size: 14.5px; }
.wz fieldset.acks .ack b { display: block; font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; }
.wz .review-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
.wz .panel > button.ghost { margin-top: 12px; }

/* ============================== the shop's tools: buttons and cards

   admin.html, production.html and screen.html load styles.css and NOT site.css, where
   .btn and .card live — so the classes those three pages have always asked for had no
   rules at all: "Print this screen" and "Save stage" drew as bare browser controls, and
   the queue's "Nothing here" card as loose text on the page. Same tokens and the same
   shapes as site.css, under `.tools`, which only those three bodies carry, so the
   marketing pages — which load both stylesheets — are untouched by this. */

.tools .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--display); font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  padding: 11px 20px; border-radius: var(--r-md); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.tools .btn-primary { background: var(--accent-fill); color: var(--on-accent); box-shadow: var(--shadow-sm); }
.tools .btn-primary:hover { background: var(--accent); }
.tools .btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.tools .btn-ghost:hover { border-color: var(--accent); }
.tools .btn[disabled] { opacity: .45; cursor: not-allowed; }
.tools .card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 20px 22px; box-shadow: var(--shadow-sm); margin-bottom: 16px;
}
.tools .card > h3 { margin: 0 0 8px; font-size: 17px; }

/* ============================== signing in to the shop's tools

   /admin, /production and /screen refuse anyone who is not on the shop's admin list, and
   the refusal is a sign-in card (web/admin-signin.js), not an error. The card is the
   account page's — same surface, same radius, same primary button. Tokens only, so both
   themes are right by construction. */

.admin-gate { max-width: 54ch; display: grid; gap: 12px; }
.admin-gate h2 { margin: 0; font-size: 22px; letter-spacing: -.01em; }
.admin-gate h2:focus-visible { outline-offset: 4px; }
.admin-gate p { margin: 0; color: var(--muted); font-size: 14.5px; line-height: 1.55; }
/* What the server said, with the address on it. Read it as text, not as a quiet aside. */
.admin-gate p.said { color: var(--ink); font-size: 15.5px; }
.admin-gate p.acts { margin-top: 4px; }
.admin-gate .card { margin: 6px 0 0; }

/* The shop's counter, press and price editor are one shared computer, so every tool page
   names the session it is holding and offers to end it. */
.signout-link {
  background: none; border: 0; padding: 0; margin: 0; font: inherit; font-size: 13px;
  color: var(--muted); text-decoration: underline; cursor: pointer;
}
.signout-link:hover { color: var(--ink); }
.signout-link[disabled] { cursor: default; text-decoration: none; }
#who .sep { color: var(--muted-off); padding: 0 3px; }

/* Nothing to show in the step rail or the saving rail while the sign-in card is up: an
   empty bordered box beside it reads as something that failed to load. [hidden] alone
   cannot turn off .steps, which sets display. */
.wz .steps[hidden], .wz .rail[hidden] { display: none; }

/* A money box holds "0.25". Full width is right for the name and email fields the order
   wizard puts in the same .field, and absurd here — the rounding step had a 770px input
   for four characters. Scoped to the price editor, which is all numbers. */
.wz.admin .panel .field input[type=text],
.wz.admin .panel .field input[type=number] {
  width: 100%; max-width: 170px; text-align: right;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.wz.admin .panel .field { margin-top: 12px; }
