/* design.css — bundle.
   Pure black and pure white. Nothing in between.

   There is one ink colour and one background colour, and they swap with the
   device theme. Body text is the same white as a heading; hierarchy comes from
   size alone, never from a dimmer grey. Greys only survive as line work and as
   the two genuinely inactive states, and those are the ink at reduced alpha
   rather than a separate colour.

   Anywhere artwork or a colour is shown, the surface underneath is real white
   paper, in both themes and at all times. A logo judged on grey is how you ship
   the wrong file.

   Everything is centred, on both axes. Corners are 3px. One accent, in two
   places: the step you are on, and the button that finishes the job.

   The app is a fixed frame: progress at the top, one step in the middle,
   navigation at the bottom. Only the middle ever scrolls. */

@font-face {
  font-family: 'Delight';
  src: url('../../../fonts/Delight-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Delight';
  src: url('../../../fonts/Delight-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Basis Grotesque Mono';
  src: url('../../../fonts/BasisGrotesqueMono-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

:root {
  --bg: #000000;
  --ink: #ffffff;

  /* Line work and the two inactive states. Same ink, held back, so there is
     still only one colour in the app. */
  --line: rgba(255, 255, 255, 0.24);
  --line-strong: rgba(255, 255, 255, 0.55);
  --dim: rgba(255, 255, 255, 0.42);

  /* The stage. These never flip. Artwork and colour are always judged here. */
  --paper: #ffffff;
  --paper-ink: #000000;
  /* Strong enough to hold a white sample against a white mount. */
  --paper-line: rgba(0, 0, 0, 0.32);

  --accent: #ff2e00;
  --ok: #35b866;
  --bad: #ff5c52;
  --wait: #e0a02c;

  --r: 3px;

  --sans: 'Delight', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'Basis Grotesque Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --pad: 34px;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #ffffff;
    --ink: #000000;
    --line: rgba(0, 0, 0, 0.2);
    --line-strong: rgba(0, 0, 0, 0.5);
    --dim: rgba(0, 0, 0, 0.4);
    --ok: #17803d;
    --bad: #c81e1e;
    --wait: #b45309;
  }
}

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

/* Any rule that sets display beats the hidden attribute, which is how a panel
   ends up on screen when the code says it is hidden. This settles it once. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection { background: var(--ink); color: var(--bg); }
::-webkit-scrollbar { width: 3px; height: 3px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line); }

button, input, textarea { font-family: var(--mono); font-size: 13px; color: inherit; }
button { cursor: pointer; }

.app {
  height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/* ---- top bar -------------------------------------------------------------- */

.topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 22px var(--pad);
  gap: 20px;
}

.wordmark {
  font-family: var(--sans);
  font-size: 17px;
  letter-spacing: -0.02em;
  color: var(--ink);
  background: none;
  border: none;
  padding: 0;
  justify-self: start;
  transition: color 0.15s ease;
}
.wordmark:hover { color: var(--accent); }

/* The client's own name. Never re-cased, because it is their spelling. */
.jobname {
  justify-self: end;
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 26ch;
}

/* Seven numbers instead of seven dots. Same footprint, and it says where you
   are rather than only how far along. */
.dots {
  display: flex;
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 10px;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}
.dots li { color: var(--dim); transition: color 0.2s ease; }
.dots li[data-state='done'] { color: var(--ink); }
.dots li[data-state='current'] { color: var(--accent); }

/* ---- stage ---------------------------------------------------------------- */

/* Dead centre, both axes. The auto margin does the centring rather than
   align-items, because an auto margin collapses to zero once the step is
   taller than the frame. Centring any other way makes the top of a long step
   unreachable: it sits above the scroll origin and nothing will scroll to it. */
.stage {
  overflow-y: auto;
  display: grid;
  align-items: start;
  justify-items: center;
  padding: 28px var(--pad);
}

.step {
  width: 100%;
  max-width: 660px;
  margin: auto;
  display: grid;
  gap: 20px;
  justify-items: center;
  text-align: center;
}
.step[hidden] { display: none; }
.step.roomy { max-width: 660px; }

h1 {
  font-family: var(--sans);
  font-size: clamp(30px, 5vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin: 0;
  font-weight: 400;
  color: var(--ink);
}

/* Body copy is the same ink as a heading. Only the size separates them. */
.lede { font-size: 13px; color: var(--ink); margin: 0; max-width: 52ch; }
.note { font-size: 12px; color: var(--ink); margin: 0; }
.note.centre { text-align: center; }
.warn { font-size: 12px; color: var(--bad); margin: 0; max-width: 52ch; }
.num { font-variant-numeric: tabular-nums; }

/* The small tracked-out label above a group. Uppercased in CSS, which is safe
   here because the text is always a word this app wrote. Never do this to a
   brand name, a colour name or an arrangement name: those are typed by the
   user and go straight into filenames. */
.field-label {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}

.stack { display: grid; gap: 10px; width: 100%; justify-items: center; }
.stack.wide { max-width: 100%; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; justify-content: center; }
.row.centre { justify-content: center; }

.field-block { display: grid; gap: 12px; width: 100%; justify-items: center; }

/* ---- drop ---------------------------------------------------------------- */

.drop {
  width: 100%;
  border: 1px dashed var(--line);
  border-radius: var(--r);
  padding: 72px 32px;
  display: grid;
  gap: 12px;
  justify-items: center;
  text-align: center;
  transition: border-color 0.15s ease;
}
.drop:hover { border-color: var(--line-strong); }
.drop.over { border-color: var(--accent); border-style: solid; }
.drop.compact { padding: 26px 28px; }
.drop.compact h1 { font-size: 18px; }
.drop.compact .lede { font-size: 12px; }

/* ---- cards --------------------------------------------------------------- */

/* Outlines, not fills. A filled card would put a third tone between the black
   and the white, which is the thing this palette is built to avoid. */
.card {
  border: 1px solid var(--line);
  background: transparent;
  border-radius: var(--r);
  padding: 22px;
  width: 100%;
  text-align: center;
}

/* The stage. White in both themes, on purpose: this is where the artwork is
   looked at, and a logo shown on anything but paper is a logo you cannot
   judge. */
.preview {
  border: 1px solid var(--line);
  border-radius: var(--r);
  height: 132px;
  display: grid;
  place-items: center;
  padding: 20px;
  background: var(--paper);
  overflow: hidden;
}
.preview svg { max-width: 100%; max-height: 92px; height: auto; }

/* Stacked and centred rather than pushed to opposite edges, so the card reads
   down the middle like everything else. */
.file-row {
  display: grid;
  justify-items: center;
  gap: 8px;
  margin-bottom: 16px;
}
.file-name { font-size: 13px; color: var(--ink); }
.file-meta { font-size: 10.5px; color: var(--dim); }

.status {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  padding: 3px 8px;
  white-space: nowrap;
  color: var(--ink);
}
.status.ok { border-color: var(--ok); color: var(--ok); }
.status.bad { border-color: var(--bad); color: var(--bad); }
.status.warn { border-color: var(--wait); color: var(--wait); }

.issue {
  display: flex;
  gap: 10px;
  justify-content: center;
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink);
  padding: 10px 14px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  text-align: center;
  margin-top: 10px;
}
.issue.block { border-color: var(--bad); }
.issue.warn { border-color: var(--wait); }
.dot { width: 5px; height: 5px; border-radius: 50%; margin-top: 9px; flex: 0 0 auto; }
.issue.block .dot { background: var(--bad); }
.issue.warn .dot { background: var(--wait); }

/* ---- controls ------------------------------------------------------------- */

input[type='text'] {
  font-family: var(--mono);
  font-size: 15px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 13px 14px;
  width: 100%;
  text-align: center;
  caret-color: var(--accent);
}
input[type='text']:focus { outline: none; border-color: var(--line-strong); }
input[type='text']::placeholder { color: var(--dim); }

input.ink {
  font-family: var(--mono);
  font-size: 12px;
  text-align: center;
  width: 42px;
  padding: 7px 2px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: transparent;
  color: var(--ink);
}
input.ink:focus { outline: none; border-color: var(--line-strong); }
input.ink.edited { border-color: var(--accent); }

.chip {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 8px 14px;
  transition: border-color 0.12s ease;
}
.chip:hover { border-color: var(--line-strong); }
.chip[aria-pressed='true'] { border-color: var(--ink); }
.chip.small { font-size: 11.5px; padding: 5px 11px; }

.btn {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  border-radius: var(--r);
  padding: 12px 24px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  transition: border-color 0.12s ease;
}
.btn:hover { border-color: var(--ink); }
/* The one loud thing in the app. It finishes the job. */
.btn.primary { background: var(--accent); border-color: var(--accent); color: #ffffff; }
.btn.primary:hover { background: var(--accent); border-color: var(--accent); color: #ffffff; opacity: 0.86; }
.btn.ghost { border-color: transparent; color: var(--dim); }
.btn.ghost:hover { border-color: transparent; color: var(--ink); }
.btn:disabled { opacity: 0.3; cursor: not-allowed; }
.btn:disabled:hover { border-color: var(--line); }
.btn.invisible { visibility: hidden; }

.link {
  font-size: 11.5px;
  color: var(--ink);
  background: none;
  border: none;
  padding: 0;
  font-family: var(--mono);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-strong);
}
.link:hover { text-decoration-color: var(--ink); }

/* ---- progress and results -------------------------------------------------- */

.bar { height: 1px; background: var(--line); overflow: hidden; margin: 26px 0 10px; width: 100%; }
.bar span { display: block; height: 100%; width: 0; background: var(--accent); transition: width 0.2s ease; }
.progress-label { font-size: 11px; color: var(--ink); letter-spacing: 0.04em; }

/* The list is taller than the box on any real job, so the last visible line
   gets cut through the middle. Fading the final rows says "keep scrolling"
   instead of looking like the render gave up. */
.tree-card {
  margin-top: 26px;
  max-height: 36vh;
  overflow: auto;
  padding: 18px 20px 26px;
  mask-image: linear-gradient(to bottom, #000 calc(100% - 34px), transparent 100%);
}
/* The one thing that is not centred. It is drawn with indentation, and centring
   it would destroy the only information it carries. */
.tree {
  font-size: 11px;
  line-height: 1.9;
  color: var(--ink);
  white-space: pre;
  margin: 0;
  text-align: left;
  display: inline-block;
}

/* ---- bottom nav ------------------------------------------------------------ */

.navbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px;
  padding: 18px var(--pad) 26px;
  border-top: 1px solid var(--line);
}
.navbar #back { justify-self: start; }
.navbar #next { justify-self: end; }
.hint { font-size: 11px; color: var(--dim); text-align: center; }

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

@media (max-width: 640px) {
  :root { --pad: 20px; }
  .step { gap: 16px; }
  .drop { padding: 48px 22px; }
  .dots { gap: 8px; font-size: 9px; }
  .jobname { display: none; }
  .preview { height: 108px; }

  /* Two deliberate rows instead of one row that overflows: name beside the
     swatch, then the hex and remove underneath. */
  .colour-top { grid-template-columns: 34px 1fr auto; row-gap: 10px; }
  .colour-top .colour-name { grid-column: 2 / -1; }
  .colour-top input.hex-input { grid-column: 1 / 3; width: 100%; }
  .colour-top .link { grid-column: 3; justify-self: end; align-self: center; }
  .colour-bottom { padding-left: 0; }

  .swatch { width: 34px; height: 34px; }
  input.pantone-input { width: 120px; }
  .cell, .matrix .head { width: 52px; min-width: 52px; }
  .cell { height: 52px; }
}
