/* Apollo Vận hành: signage for a working day. Phone first, then wider screens.
   No outside fonts or images; pictograms are inline SVG drawn with currentColor.

   The world: white paper, near-black ink, a black top bar, black pictogram squares. Signal
   yellow means «next» and «you are here», and nothing else: the sign at the top of a working
   screen, the current menu item, the ring a guided tour puts on what to press. Green says done
   and red says wrong, only where they mean it. */

:root {
  color-scheme: light;
  --ink: #14171a;
  --ink-2: #3b434b;
  --paper: #ffffff;
  /* The page is paper too: sections are ruled in ink, not boxed white on grey. */
  --ground: #ffffff;
  --hover: #eef0f2;
  --line: #d4d8dc;
  --line-strong: #6f7881;
  --yellow: #ffcc00;
  --yellow-deep: #e0b000;
  --navy: #134868;
  --navy-dark: #0c3049;
  --ok: #1d7a34;
  --ok-bg: #e9f5ec;
  --bad: #c42a1f;
  --bad-ink: #8f1d14;
  --bad-bg: #fdeceb;
  --info-ink: #0f3d5c;
  --info-bg: #e7f0f7;
  --focus: #1a5fd0;
  --radius: 0.375rem;
  --radius-lg: 0.5rem;
  --text-xs: 0.8125rem;
  --text-sm: 0.9375rem;
  --text-lg: 1.125rem;
  --text-h2: 1.125rem;
  --text-h1: 1.5rem;
  --text-sign: 2.75rem;
  --bar: 3.5rem;
  --font: "Segoe UI", system-ui, -apple-system, Roboto, "Noto Sans", sans-serif;
}

/* ───────────────────────────── base ───────────────────────────── */

* {
  box-sizing: border-box;
}

html {
  /* A focused field scrolled into view stays clear of the bar and a sticky sign. */
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink);
  background: var(--ground);
  text-wrap: pretty;
  accent-color: var(--ink);
  -webkit-text-size-adjust: 100%;
}

::selection {
  background: #cde0f6;
  color: var(--ink);
}

a {
  color: var(--navy);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--navy-dark);
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.skip {
  position: absolute;
  left: 0.5rem;
  top: -4rem;
  z-index: 20;
  padding: 0.625rem 0.875rem;
  background: var(--yellow);
  color: var(--ink);
  font-weight: 700;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
}

.skip:focus {
  top: 0.5rem;
}

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

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

h1,
h2,
h3 {
  text-wrap: balance;
  line-height: 1.25;
}

h1 {
  font-size: var(--text-h1);
  margin: 0.25rem 0 1rem;
  letter-spacing: -0.01em;
}

h2 {
  font-size: var(--text-h2);
  margin: 1.75rem 0 0.625rem;
}

h3 {
  font-size: 1.0625rem;
  margin: 1.25rem 0 0.375rem;
}

p {
  margin: 0.5rem 0;
}

/* Running text keeps to a readable measure: 65ch holds 74 to 78 Vietnamese letters a line in
   the system font. Only a paragraph of the page or of a card (an invite's sits in the card's
   second column): a part of a row fills its own line, and a message is a banner across the page
   that keeps its words to the same measure inside (see .msg). */
.page > p:not(.msg),
.card > p:not(.msg),
.invite p,
.note,
.lede {
  max-width: 65ch;
}

.note {
  color: var(--ink-2);
  font-size: var(--text-sm);
}

.lede {
  color: var(--ink-2);
  margin: -0.25rem 0 1.25rem;
}

code {
  font-family: ui-monospace, Consolas, "Cascadia Mono", monospace;
  font-size: 0.875rem;
  overflow-wrap: anywhere;
}

.plain {
  margin: 0.25rem 0;
  padding-left: 1.25rem;
}

.plain li {
  margin: 0.25rem 0;
}

/* ───────────────────────────── shell ───────────────────────────── */

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 0.75rem;
  min-height: var(--bar);
  padding: 0.375rem 1rem;
  background: var(--ink);
  color: #ffffff;
}

.brand {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: #ffffff;
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: 0.01em;
  text-decoration: none;
}

.brand:hover {
  color: var(--yellow);
}

.who {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.who form {
  margin: 0;
}

.who-name {
  color: #e6e9ec;
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.who-roles {
  color: #c2c8ce;
}

/* On a phone the bar keeps one line: the roles are on the home page, a long name ends in «…». */
@media (max-width: 47.99rem) {
  .who-roles {
    display: none;
  }
}

@media (max-width: 29.99rem) {
  .who-name {
    max-width: 7rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .button-onbar .icon {
    display: none;
  }
}

/* The menu: one row that scrolls sideways on a phone, a rail at the left from 64rem. The page
   itself never scrolls sideways. */
.nav {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}

.nav ul {
  display: flex;
  gap: 0.25rem;
  margin: 0;
  padding: 0.375rem 0.5rem;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}

.nav li {
  flex: none;
}

/* Positioned, so the hidden words of a badge stay inside the row that scrolls: placed by the
   page instead, they would widen it to the end of the row (1212 px on a 412 px phone). */
.nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.25rem 0.625rem 0.25rem 0.375rem;
  border: 2px solid transparent;
  border-radius: var(--radius);
  color: var(--ink);
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
}

.nav a:hover {
  background: var(--hover);
  color: var(--ink);
}

.nav-pic {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: 0.25rem;
  background: var(--ink);
  color: #ffffff;
}

.nav-pic .icon {
  width: 1.125rem;
  height: 1.125rem;
}

/* You are here: the square turns yellow, the label goes bold. */
.nav a[aria-current="page"] {
  font-weight: 700;
}

.nav a[aria-current="page"] .nav-pic {
  background: var(--yellow);
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--ink);
}

/* On a phone the row is tighter, and fades at its end to say there is more to scroll. After the
   item's own rules above, which win otherwise: written before them, the items never got tighter,
   and a packer's three items ran to 359 px on a 320 px phone, cut with no fade. */
@media (max-width: 63.99rem) {
  .nav {
    position: relative;
  }

  .nav::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 1px;
    width: 1.5rem;
    background: linear-gradient(to right, rgb(255 255 255 / 0), var(--paper));
    pointer-events: none;
  }
}

@media (max-width: 29.99rem) {
  .nav ul {
    gap: 0;
    padding-inline: 0.25rem 0.75rem;
  }

  .nav a {
    gap: 0.3125rem;
    padding: 0.25rem;
    font-size: 0.9375rem;
  }

  /* Trang chủ is always first: its house says it, and its name stays for a screen reader, so a
     driver's or a packer's three items fit at 320 px with their counts. */
  .nav li:first-child .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Three items or fewer fit without scrolling from 320 px, with a count of two figures (a
     packer's row is 317 px): no end room, no fade. */
  .nav ul:not(:has(li:nth-child(4))) {
    padding-inline-end: 0.25rem;
  }

  .nav:not(:has(li:nth-child(4)))::after {
    display: none;
  }

  .nav .badge {
    min-width: 1.25rem;
    padding: 0 0.25rem;
    line-height: 1.25rem;
  }

  .nav .nav-pic {
    width: 1.75rem;
    height: 1.75rem;
  }
}

.badge {
  display: inline-block;
  min-width: 1.5rem;
  margin-left: auto;
  padding: 0 0.375rem;
  border-radius: 999px;
  background: var(--ink);
  color: #ffffff;
  font-size: var(--text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.5rem;
  text-align: center;
}

.badge[hidden] {
  display: none;
}

/* ───────────────────────────── page ───────────────────────────── */

.page {
  width: 100%;
  max-width: 72rem;
  min-width: 0;
  margin: 0 auto;
  padding: 1rem 1rem 3rem;
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin: 0.25rem 0 1rem;
}

.page-head h1 {
  margin: 0;
}

.page-head .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
}

.page-meta {
  margin: -0.5rem 0 1rem;
  color: var(--ink-2);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

/* A section of a screen is ruled in ink across its top, as a panel of a sign is framed: no
   white box on a grey field. */
.card {
  margin: 1.75rem 0;
  padding: 0.75rem 0 0;
  border-top: 2px solid var(--ink);
}

.card > h2:first-child,
.card > .card-head:first-child h2 {
  margin-top: 0;
}

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

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin-bottom: 0.5rem;
}

.card-head h2 {
  margin: 0;
}

/* A group with nothing in it steps back. */
.card.is-quiet {
  border-top: 2px dashed var(--line-strong);
  color: var(--ink-2);
}

.facts-under {
  margin-top: 0.875rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
}

.count {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--ink-2);
}

/* ───────────────────────────── the sign ─────────────────────────────
   One sentence of what to do next, the count as large as a gate number. */

.sign {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "pic text count";
  align-items: start;
  gap: 0.75rem;
  margin: 0 0 1.25rem;
  padding: 0.875rem 1rem;
  background: var(--yellow);
  color: var(--ink);
  border-radius: var(--radius-lg);
  view-transition-name: sign;
}

.sign-pic {
  grid-area: pic;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 0.25rem;
  background: var(--ink);
  color: #ffffff;
}

.sign-pic .icon {
  width: 1.625rem;
  height: 1.625rem;
}

.sign-text {
  grid-area: text;
  min-width: 0;
}

.sign-title {
  margin: 0.125rem 0 0;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.3;
}

.sign-line {
  margin: 0.25rem 0 0;
  max-width: 60ch;
  color: var(--ink);
  font-size: var(--text-sm);
}

.sign-count {
  grid-area: count;
  margin: 0;
  font-size: var(--text-sign);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.sign-unit {
  font-size: var(--text-lg);
  letter-spacing: 0;
}

.sign-progress {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem 0.75rem;
  margin: 0.625rem 0 0;
}

.pips {
  display: flex;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pips li {
  width: 1.75rem;
  height: 0.375rem;
  border-radius: 0.1875rem;
  background: rgb(20 23 26 / 0.22);
}

.pips li.is-done {
  background: var(--ink);
}

.pips li.is-now {
  background: var(--ink);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.sign-meta {
  margin: 0;
  font-size: var(--text-xs);
  font-weight: 600;
}

.sign-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.sign-actions form {
  margin: 0;
}

/* Nothing waits: the same sign on paper in an ink frame, the count 0. Yellow keeps one meaning. */
.sign-rest {
  background: var(--paper);
  box-shadow: inset 0 0 0 2px var(--ink);
}

.sign-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.5rem;
  margin-top: 0.25rem;
  color: var(--ink);
  font-weight: 700;
}

.sign-link:hover {
  color: var(--ink);
}

/* On a phone the pictogram and the count share the top line, and the sentence takes the whole
   width under them: at 320 px a third column would leave it a hundred and sixty pixels. */
@media (max-width: 29.99rem) {
  .sign {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "pic count"
      "text text";
    align-items: center;
    gap: 0.5rem 0.75rem;
  }

  .sign-count {
    justify-self: end;
    font-size: 2.25rem;
  }
}

/* ───────────────────────────── messages ───────────────────────────── */

.messages {
  margin: 0 0 1rem;
}

/* A banner spans its line, but its words keep the measure of running text: past 65ch the
   padding at the end takes the rest. A percentage of padding is of the width the banner fills;
   the 2px are its two borders. On a phone the padding stays 0.875rem. */
.msg {
  margin: 0.5rem 0;
  padding: 0.625rem 0.875rem;
  padding-inline-end: max(0.875rem, 100% - 65ch - 0.875rem - 2px);
  border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  border-radius: var(--radius);
  font-weight: 500;
}

.msg-success {
  background: var(--ok-bg);
  color: #145c27;
}

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

.msg-error,
.msg-warning {
  background: var(--bad-bg);
  color: var(--bad-ink);
}

/* ───────────────────────────── buttons ─────────────────────────────
   Primary is ink, secondary has an ink outline, danger is red. Every one is at least 44 px
   high; the quiet one 40 px. */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 120ms ease-out,
    color 120ms ease-out;
}

.button:hover {
  background: var(--hover);
  color: var(--ink);
}

.button:active {
  transform: translateY(1px);
}

.button:disabled,
.button[aria-disabled="true"] {
  border-color: var(--line-strong);
  color: var(--ink-2);
  cursor: not-allowed;
}

.button-primary,
.button-ink {
  background: var(--ink);
  color: #ffffff;
}

.button-primary:hover,
.button-ink:hover {
  background: #2c3237;
  color: #ffffff;
}

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

.button-danger:hover {
  background: var(--bad-bg);
  color: var(--bad-ink);
}

.button-quiet {
  min-height: 2.5rem;
  padding: 0.25rem 0.75rem;
  border-width: 1px;
  border-color: var(--line-strong);
  font-weight: 500;
}

/* On the black bar. */
.button-onbar {
  min-height: 2.5rem;
  padding: 0.25rem 0.75rem;
  border-color: #ffffff;
  background: transparent;
  color: #ffffff;
}

.button-onbar:hover {
  background: #ffffff;
  color: var(--ink);
}

/* On the yellow sign. */
.button-sign {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}

.button-sign:hover {
  background: rgb(255 255 255 / 0.55);
  color: var(--ink);
}

.button-sign-quiet {
  min-height: 2.5rem;
  border-color: transparent;
  background: transparent;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.button-sign-quiet:hover {
  background: rgb(255 255 255 / 0.4);
  color: var(--ink);
}

/* The big press of a phone screen: Nhận đơn, Lập bảng kê. */
.button-big {
  min-height: 3rem;
  padding: 0.625rem 1.25rem;
  font-size: 1.0625rem;
}

/* A toggle that is on: Đã test máy, Đã dán tem. */
.button-done {
  border-color: var(--ok);
  background: var(--ok-bg);
  color: #145c27;
}

.button-done:hover {
  background: #d8eedf;
  color: #145c27;
}

.button .icon {
  width: 1.125rem;
  height: 1.125rem;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0;
}

.actions form {
  margin: 0;
}

/* ───────────────────────────── forms ───────────────────────────── */

.form {
  display: grid;
  gap: 1rem;
  max-width: 44rem;
  margin: 0.75rem 0;
}

.form .button {
  justify-self: start;
}

.form-wide {
  max-width: 56rem;
}

/* Fields that sit side by side when there is room, one under another on a phone. */
.field-grid {
  display: grid;
  gap: 0.875rem 1rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.choices .field + .field,
.choices .field + .field-grid,
.choices .field-grid + .field {
  margin-top: 0.875rem;
}

/* The column is the field's width: a date input's own minimum must not push it past the column. */
.field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.3125rem;
}

.field label {
  font-weight: 600;
}

.field > .note {
  margin: 0;
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="search"],
input[type="number"],
input[type="date"],
input[type="datetime-local"],
input[type="file"],
select,
textarea {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
}

input::placeholder,
textarea::placeholder {
  color: #59626b;
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--ink);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: var(--ink);
}

input[type="file"] {
  padding: 0.375rem;
}

input[type="file"]::file-selector-button {
  min-height: 2.25rem;
  margin-right: 0.75rem;
  padding: 0.25rem 0.75rem;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

select {
  appearance: none;
  padding-right: 2.5rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2314171a' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-position: right 0.75rem center;
  background-repeat: no-repeat;
  background-size: 1.125rem;
}

textarea {
  resize: vertical;
  /* What someone is typing must not rewrap under their fingers. */
  text-wrap: wrap;
}

input[aria-invalid="true"] {
  border: 2px solid var(--bad);
}

.field-error {
  margin: 0.125rem 0 0;
  color: var(--bad-ink);
  font-weight: 600;
}

.choices {
  min-width: 0;
  margin: 0;
  padding: 0.75rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
}

/* Floated, the legend is the group's title inside its box. Left on the border, a legend that
   wraps shows its first line outside the box and the rest inside, as on Settings at 390 px. */
.choices legend {
  float: left;
  width: 100%;
  margin: 0 0 0.25rem;
  padding: 0;
  font-weight: 700;
}

.choices legend + * {
  clear: left;
}

/* Inside a card the card is the box: the group keeps its legend, on a rule. */
.card .choices {
  padding: 0.75rem 0 0;
  border-width: 1px 0 0;
  border-radius: 0;
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  min-height: 2.75rem;
  padding: 0.5rem 0;
}

.check input {
  width: 1.375rem;
  height: 1.375rem;
  margin: 0.0625rem 0 0;
  flex: none;
}

.search {
  margin: 1rem 0;
}

.search label {
  display: block;
  margin-bottom: 0.3125rem;
  font-weight: 600;
}

.search-row {
  display: flex;
  gap: 0.5rem;
}

.search-row input {
  flex: 1;
  min-width: 0;
}

/* Filters: as many columns as fit, each at least 10rem. */
.filters {
  display: grid;
  gap: 0.75rem 1rem;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}

.filter-bar {
  max-width: none;
  padding: 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.filter-bar .filter-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
}

.filter-bar .check {
  padding: 0;
}

/* The filters past the order code fold under «Thêm bộ lọc» on a phone, so the list shows first.
   From 64rem the script opens them and the summary steps out of the way; without the script they
   stay one press away. */
.filter-more > summary {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  cursor: pointer;
  list-style: none;
}

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

.filter-more > summary:hover {
  text-decoration-thickness: 2px;
}

.filter-more[open] > summary {
  margin-bottom: 0.5rem;
}

.filter-more-count {
  font-weight: 400;
  white-space: pre;
}

/* The order code alone on its line: the whole width on a phone, one wide column on a desk. */
.filters.filters-lead {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
}

/* What the list is filtered by, when a folded filter is in use. */
.filter-summary {
  max-width: 65ch;
  margin: 0.75rem 0 0;
  color: var(--ink-2);
}

@media (min-width: 64rem) {
  .filter-more[open] > summary {
    display: none;
  }
}

/* The sign-in page: what the app is, in words, then the one press. Side by side from 48rem. */
.login {
  display: grid;
  gap: 1.75rem;
  max-width: 64rem;
  margin: 1rem auto 0;
}

.login-brand {
  padding-top: 0.75rem;
  border-top: 2px solid var(--ink);
}

.login-name {
  margin: 0;
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.login-what {
  max-width: 34rem;
  margin: 0.5rem 0 1rem;
  font-size: var(--text-lg);
}

.login-axes {
  max-width: 30rem;
}

.login-how {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  max-width: 34rem;
  margin: 1rem 0 0;
  font-weight: 600;
}

.login-box h1 {
  margin-top: 0;
}

@media (min-width: 48rem) {
  .login {
    grid-template-columns: minmax(0, 1.2fr) minmax(18rem, 1fr);
    align-items: start;
    gap: 3rem;
    margin-top: 2.5rem;
  }

  .login-box {
    padding: 1.5rem;
    border: 2px solid var(--ink);
    border-radius: var(--radius-lg);
  }
}

/* The big search of Bảo hành: what the desk does first. */
.search-big {
  max-width: 44rem;
  padding: 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.search-big input {
  min-height: 3rem;
  font-size: var(--text-lg);
}

.search-big .button {
  min-height: 3rem;
}

.summary-title {
  display: flex;
  align-items: center;
  min-height: 2.75rem;
  font-weight: 700;
  cursor: pointer;
}

.days-left {
  margin: 0 0 0.75rem;
  font-weight: 600;
}

.days-count {
  font-size: 2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.days-left.is-over {
  color: var(--bad-ink);
}

/* Settings: what the server reports about itself, one ruled line each; a line that reports a
   failure is red, as everything that failed is. */
.status-lines {
  margin: 0;
  padding: 0;
  list-style: none;
}

.status-lines li {
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
  overflow-wrap: anywhere;
}

.status-lines li:first-child {
  border-top: 0;
}

.status-lines li.is-bad {
  color: var(--bad-ink);
  font-weight: 600;
}

/* Under a line at risk, what to do about it: in ink, at a readable measure. */
.status-lines .todo {
  display: block;
  max-width: 65ch;
  margin-top: 0.125rem;
  color: var(--ink);
  font-weight: 400;
}

/* ───────────────────────────── chips ───────────────────────────── */

.tag,
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.0625rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--ink);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.tag-locked,
.chip-bad {
  border-color: var(--bad);
  background: var(--bad);
  color: #ffffff;
}

.chip-ok {
  border-color: var(--ok);
  background: var(--ok-bg);
  color: #145c27;
}

.chip-off {
  border-color: var(--line);
  background: none;
  color: var(--ink-2);
}

.chip-run {
  border: 2px solid var(--ink);
  padding: 0 0.4375rem;
}

.chip-wait {
  border-style: dashed;
  color: var(--ink-2);
}

.chip .icon {
  width: 0.875rem;
  height: 0.875rem;
  stroke-width: 3;
}

/* Sums that matter: the cash a driver holds, an order's lines. */
.money,
.money-big {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.money-big {
  font-size: 1.5rem;
}

.money-lines {
  display: grid;
  gap: 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.money-lines li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  overflow-wrap: anywhere;
}

.money-lines .money {
  font-weight: 600;
}

.money-total {
  margin-top: 0.25rem;
  padding-top: 0.5rem;
  border-top: 2px solid var(--ink);
  font-weight: 700;
  font-size: var(--text-lg);
}

a.call {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ───────────────────────────── the three axes ─────────────────────────────
   Đơn, Tiền, Hàng always in that order and in the same place, on every order. */

.axes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.axis {
  display: grid;
  align-content: start;
  min-width: 0;
  padding: 0.3125rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  font-size: var(--text-xs);
  line-height: 1.35;
}

.axis-name {
  font-weight: 700;
}

.axis-state {
  font-size: var(--text-sm);
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* Done steps back: green words and a tick on paper, never a filled cell louder than the work
   still moving. */
.axis-ok {
  border-color: var(--ok);
  color: #145c27;
}

.axis .icon {
  width: 0.875rem;
  height: 0.875rem;
  margin-right: 0.125rem;
  stroke-width: 3;
  vertical-align: -0.125rem;
}

.axis-run {
  border: 2px solid var(--ink);
  padding: 0.25rem 0.4375rem;
}

.axis-wait {
  border-style: dashed;
  color: var(--ink-2);
}

.axis-bad {
  border-color: var(--bad);
  background: var(--bad);
  color: #ffffff;
}

.axis-off {
  border-color: var(--line);
  background: none;
  color: var(--ink-2);
}

/* A shipment more than the three columns hold starts a row of its own. */
.axes > :nth-child(n + 4) {
  grid-column: 3;
}

/* ───────────────────────────── rows of a list ───────────────────────────── */

.rows {
  margin: 0.5rem 0;
  padding: 0;
  list-style: none;
}

/* A list reads as the lines of a board: one rule between rows, none of them a box. */
.row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.375rem;
  margin: 0;
  padding: 0.875rem 0;
  border-top: 1px solid var(--line-strong);
}

.rows {
  border-bottom: 1px solid var(--line-strong);
}

/* A line for each part of a row, except tags: they share one, and a long one wraps. */
.row > * {
  flex-basis: 100%;
}

.row > .tag,
.row > .chip {
  flex-basis: auto;
  white-space: normal;
}

/* Lines of text sit close, whether p or span. A message, and what acts on the row, stand apart. */
.row > .row-meta {
  margin: 0;
}

.row > .msg {
  margin: 0.25rem 0 0;
}

.row > form,
.row > .filters,
.row > .actions {
  margin: 0.5rem 0 0;
}

/* Inside a card the rows share its box: a rule between them, no box of their own. */
.card .rows {
  border-bottom: 0;
}

.card .row:last-child {
  padding-bottom: 0.25rem;
}

.row-title {
  font-weight: 700;
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
}

a.row-title {
  color: var(--navy);
}

.row-meta {
  color: var(--ink-2);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

/* An order's row: code and where, the three axes, the sum. */
.row-order {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "main total"
    "axes axes";
  gap: 0.5rem 0.75rem;
}

.row-order > * {
  flex-basis: auto;
}

.row-main {
  grid-area: main;
  min-width: 0;
}

.row-main > p {
  margin: 0.125rem 0 0;
}

.row-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
}

.row-order .axes {
  grid-area: axes;
}

.row-total {
  grid-area: total;
  margin: 0;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* Heads over the columns of an order list, from 48rem; each cell keeps its own name for a
   screen reader. */
.rows-head {
  display: none;
}

@media (min-width: 48rem) {
  .rows-head {
    display: grid;
    grid-template-columns: minmax(10rem, 1.2fr) minmax(0, 3fr) 9rem;
    gap: 0 0.75rem;
    padding: 0 0 0.375rem;
    color: var(--ink-2);
    font-size: var(--text-xs);
    font-weight: 700;
  }

  .rows-head .head-axes {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.375rem;
  }

  .rows-head .head-total {
    text-align: right;
  }

  .has-head .row-order .axis-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

.groups-empty {
  margin: 1.75rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--ink-2);
}

.groups-empty li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0;
  border-top: 1px dashed var(--line-strong);
}

.card-head .count {
  color: var(--ink);
  font-size: var(--text-lg);
}

/* Work that is finished steps back. */
.row.is-quiet {
  background: none;
}

.row.is-quiet .row-title,
.row.is-quiet .row-total {
  color: var(--ink-2);
}

/* ───────────────────────────── facts, steps, lines ───────────────────────────── */

.facts {
  display: grid;
  gap: 0.375rem;
  margin: 0;
}

.facts div {
  display: grid;
  gap: 0.125rem 0.75rem;
  grid-template-columns: minmax(6rem, 9rem) minmax(0, 1fr);
}

.facts dt {
  color: var(--ink-2);
}

.facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.steps > form {
  margin: 0;
}

/* A closed step is its press, side by side with the others; an opened one takes the whole line. */
.step:not([open]) {
  flex: 0 1 auto;
}

.step {
  flex: 1 1 100%;
  max-width: 40rem;
}

.step > summary {
  display: inline-flex;
  list-style: none;
  cursor: pointer;
}

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

.step[open] > summary {
  margin-bottom: 0.5rem;
}

.step[open] {
  padding: 0 0 0.75rem;
  border-bottom: 1px solid var(--line);
}

.step > .form {
  margin-top: 0;
}

/* «Việc tiếp theo» on an order or a record: the steps this person can take now. */
.next-panel {
  padding: 1rem;
  background: var(--yellow);
  border: 0;
  border-radius: var(--radius-lg);
}

/* No step of one's own: a plain line says whose move it is, without yellow. */
.next-line p {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin: 0;
  font-weight: 600;
}

.next-line-pic {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  border-radius: 0.25rem;
  background: var(--ink);
  color: #ffffff;
}

.next-line-pic .icon {
  width: 1rem;
  height: 1rem;
}

/* On a phone each press of the panel takes the whole width. */
@media (max-width: 29.99rem) {
  .next-panel .step,
  .next-panel .step > summary,
  .next-panel .steps > form,
  .next-panel .steps > form .button,
  .next-work .button {
    width: 100%;
  }
}

/* The work of one's own on a shipment, when the order itself has no step for this person: which
   shipment, what waits there, and the way to it. */
.next-work {
  display: grid;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.next-work li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.next-work p {
  max-width: 60ch;
  margin: 0;
}

/* What a packer still has to do before «Báo sẵn sàng»: the tour's numbered steps, ticked green. */
.packing-todo {
  margin: 0.75rem 0 0;
}

.packing-todo-title {
  margin: 0;
  font-weight: 700;
}

.next-panel h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.next-panel .step[open] {
  padding: 0.75rem;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--paper);
}

.lines {
  margin: 0.5rem 0;
  padding: 0;
  list-style: none;
}

.line {
  padding: 0.75rem 0;
  border-top: 1px solid var(--line);
}

.line-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.5rem;
}

.line-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.line-actions form {
  margin: 0;
}

.line-table {
  display: grid;
  gap: 0.5rem;
}

.line-row {
  display: grid;
  gap: 0.5rem 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  padding: 0.75rem 0;
  border-top: 1px solid var(--line);
}

.serials {
  margin: 0.25rem 0;
  padding: 0;
  list-style: none;
}

.serials li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.125rem 0;
  font-family: ui-monospace, Consolas, "Cascadia Mono", monospace;
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.serial-form {
  margin-top: 0.5rem;
}

.photos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.75rem 0;
  padding: 0;
  list-style: none;
}

.photos a {
  display: block;
  min-width: 3rem;
  min-height: 3rem;
}

.photos img {
  display: block;
  max-width: 10rem;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.photos form {
  margin: 0.375rem 0 0;
}

.timeline {
  margin: 0;
  padding: 0;
  list-style: none;
}

.timeline li {
  position: relative;
  padding: 0.25rem 0 0.25rem 1.25rem;
  border-left: 2px solid var(--line);
  overflow-wrap: anywhere;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: -0.4375rem;
  top: 0.75rem;
  width: 0.75rem;
  height: 0.75rem;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: var(--paper);
}

.timeline time {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.scan-video {
  display: block;
  width: 20rem;
  max-width: 100%;
  margin-top: 0.5rem;
  border-radius: var(--radius);
}

/* Bốn mốc: numbered marks on a rail, the way a tour's steps read, so they are not taken for boxes
   to tick; a milestone still waiting has a dashed ring and its number, a done one is green with a
   tick, the next one stands out. */
.milestones {
  margin: 0;
  padding: 0;
  list-style: none;
}

.milestone {
  position: relative;
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  gap: 0.5rem;
  padding: 0.625rem 0;
  border-top: 1px solid var(--line);
}

/* The rail from one mark to the next. */
.milestone:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 2.375rem;
  bottom: -0.625rem;
  left: 0.6875rem;
  width: 2px;
  background: var(--line);
}

.milestone:first-child {
  border-top: 0;
}

.milestone-mark {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.0625rem;
  border: 2px dashed var(--line-strong);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink-2);
  font-size: var(--text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.milestone.is-done .milestone-mark {
  border: 2px solid var(--ok);
  background: var(--ok);
  color: #ffffff;
}

.milestone-mark .icon {
  width: 1rem;
  height: 1rem;
  stroke-width: 3;
}

.milestone.is-next .milestone-mark {
  border: 2px solid var(--ink);
  color: var(--ink);
  box-shadow: 0 0 0 3px var(--yellow);
}

.milestone-title {
  margin: 0;
  font-weight: 700;
}

.milestone-detail {
  margin: 0.125rem 0 0;
  color: var(--ink-2);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

/* The three axes as large cells on an order's own page. */
.axes-big .axis {
  padding: 0.625rem 0.75rem;
  font-size: var(--text-sm);
}

.axes-big .axis-run {
  padding: 0.5625rem 0.6875rem;
}

.axes-big .axis-name {
  font-size: var(--text-xs);
  text-transform: none;
}

.axes-big .axis-state {
  font-size: 1rem;
  font-weight: 700;
}

.axes-big .axis-more {
  margin-top: 0.125rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.next-panel .sign-pic {
  width: 2.25rem;
  height: 2.25rem;
}

.next-panel .sign-pic .icon {
  width: 1.25rem;
  height: 1.25rem;
}

/* ───────────────────────────── board ───────────────────────────── */

/* The page of the board takes the whole width: on a screen wider than the page, more columns
   show, and the last one is still cut at the edge of the screen, not at the edge of the page. */
.page:has(> .board) {
  max-width: none;
}

/* Out over the page's margin, so a column is cut at the edge of the screen and not inside the
   margin. With a column's own padding, the first card stays in line with the page's text. */
.board {
  position: relative;
  display: flex;
  gap: 1rem;
  margin-inline: -1rem;
  padding: 0 0.5rem 0.75rem;
  overflow-x: auto;
  scrollbar-color: var(--line-strong) transparent;
}

.board-column {
  flex: 0 0 20rem;
  padding: 0.5rem 0 0;
  border-top: 3px solid var(--ink);
}

.board-column h2 {
  display: flex;
  justify-content: space-between;
  margin: 0.25rem 0.25rem 0.5rem;
  font-size: 1rem;
}

.board-column .row-order {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "main"
    "total"
    "axes";
}

.board-column .row-total {
  text-align: left;
}

/* On the board the three cells are tighter, so a state reads on one or two lines, not three. */
.board-column .axis {
  padding: 0.25rem 0.375rem;
}

.board-column .axis-state {
  font-size: var(--text-xs);
  line-height: 1.3;
}

/* ───────────────────────────── pager, tabs ───────────────────────────── */

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin: 1rem 0;
}

.pager a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
}

.tabs {
  margin: 0.75rem 0 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.tabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0;
  padding: 0.375rem;
  list-style: none;
}

.tabs a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 0.875rem;
  border-radius: var(--radius);
  color: var(--ink);
  white-space: nowrap;
  text-decoration: none;
}

.tabs a:hover {
  background: var(--hover);
}

.tabs a[aria-current="page"] {
  background: var(--ink);
  color: #ffffff;
  font-weight: 700;
}

/* ───────────────────────────── home ───────────────────────────── */

.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.work-tile {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  min-height: 4.5rem;
  padding: 0.75rem 1rem;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  color: var(--ink);
  text-decoration: none;
}

.work-tile:hover {
  background: var(--hover);
  color: var(--ink);
}

.work-tile .nav-pic {
  width: 2.5rem;
  height: 2.5rem;
}

.work-label {
  font-weight: 600;
  line-height: 1.3;
}

.work-count {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.empty {
  margin: 0.5rem 0;
  padding: 1rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  color: var(--ink-2);
  background: var(--paper);
}

/* Inside a card the card is the box: the empty line is only words. */
.card .empty {
  padding: 0;
  border: 0;
  background: none;
}

/* The home page: the person's work at the left; from 64rem the rest stands in a column at the
   right, so the work keeps the width. */
.home {
  display: grid;
  gap: 0 2rem;
  align-items: start;
}

.home-main,
.home-side {
  min-width: 0;
}

@media (min-width: 64rem) {
  .home {
    grid-template-columns: minmax(0, 1.7fr) minmax(17rem, 1fr);
  }
}

.home-guide .tour-progress {
  max-width: 24rem;
  margin-top: 0.25rem;
}

.home-suggest {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.home-suggest p {
  flex: 1 1 18rem;
  max-width: 65ch;
  margin: 0;
}

/* The list of what one's roles may do is long and read once: folded under its summary. */
.rights > summary {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

.invite {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.75rem 1rem;
  align-items: start;
}

.invite .actions {
  grid-column: 2;
  margin: 0;
}

.invite p {
  margin: 0.125rem 0 0;
}

.invite-title {
  font-weight: 700;
}

/* ───────────────────────────── tours and badges ───────────────────────────── */

/* The quest book: one ruled section per role, its intro tour on top, then a line per quest, read
   as a task list (what job, how far, the press). From 64rem two roles stand side by side. */
.quest-books {
  display: grid;
  gap: 0 2rem;
  align-items: start;
}

.quest-book-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1rem;
}

.quest-book-head .tour-progress {
  flex: 1 1 12rem;
  max-width: 20rem;
  margin: 0;
}

.quests-title {
  margin: 1.25rem 0 0;
}

.quests {
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
}

.quest {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "pic text chip"
    "pic act act";
  align-items: start;
  gap: 0.5rem 0.75rem;
  padding: 0.875rem 0;
  border-top: 1px solid var(--line-strong);
}

.quest:last-child {
  border-bottom: 1px solid var(--line-strong);
}

.quest-pic {
  grid-area: pic;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.25rem;
  background: var(--ink);
  color: #ffffff;
}

.quest-text {
  grid-area: text;
}

.quest > .chip {
  grid-area: chip;
}

.quest-act {
  grid-area: act;
}

.quest-title {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 700;
}

.quest-pitch {
  margin: 0.125rem 0 0;
  color: var(--ink-2);
  font-size: var(--text-sm);
}

/* A quest being done is «you are here»; a finished one steps back, its pictogram turned green. */
.quest.is-learning .quest-pic {
  background: var(--yellow);
  box-shadow: inset 0 0 0 2px var(--ink);
  color: var(--ink);
}

.quest.is-done .quest-pic {
  background: var(--ok);
}

.quest.is-done .quest-title {
  color: var(--ink-2);
}

@media (min-width: 48rem) {
  .quest {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "pic text chip act";
    align-items: center;
  }
}

@media (min-width: 64rem) {
  .quest-books {
    grid-template-columns: repeat(auto-fit, minmax(30rem, 1fr));
  }

  /* One role alone takes the width a page of reading holds, not half the screen. */
  .quest-books > .quest-book:only-child {
    max-width: 48rem;
  }
}

/* The moment a tour or a quest is finished: green says done, and the stamp turns in once. Off for a
   person who asked for less motion, like every animation here. */
.quest-done {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  margin: 0 0 1.75rem;
  padding: 1rem;
  border: 2px solid var(--ok);
  border-radius: var(--radius-lg);
  background: var(--ok-bg);
  color: #145c27;
}

.quest-done h2 {
  margin: 0 0 0.25rem;
  /* A quest's name runs long: two lines on a phone need room between them. */
  line-height: 1.3;
}

.quest-done p {
  max-width: 60ch;
  margin: 0 0 0.75rem;
}

.quest-done-text > :last-child {
  margin-bottom: 0;
}

/* The next quest's name makes a long press: on a phone it runs on two lines, with room between. */
.quest-done .button {
  line-height: 1.3;
  text-align: left;
}

.quest-done-stamp {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  flex: none;
  border-radius: 50%;
  background: var(--ok);
  color: #ffffff;
  animation: stamp-in 320ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.quest-done-stamp .icon {
  width: 1.75rem;
  height: 1.75rem;
}

@keyframes stamp-in {
  from {
    transform: scale(1.6) rotate(-18deg);
    opacity: 0;
  }
}

/* The administrator's look at another role's book: folded, one line each. */
.quest-book-other {
  margin-top: 0.75rem;
}

.quest-book-other > summary {
  min-height: 2.75rem;
  padding: 0.5rem 0;
  font-weight: 600;
  cursor: pointer;
}


.tours {
  display: grid;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A tour is the board's content card: paper in an ink frame, the pictogram at the left. */
.tour {
  padding: 1rem;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
}

.tour.is-learning {
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 4px var(--yellow);
}

.tour-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: 0.75rem;
}

.tour-pic {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 0.25rem;
  background: var(--ink);
  color: #ffffff;
}

.tour-pic .icon {
  width: 1.75rem;
  height: 1.75rem;
}

/* Done is green: yellow stays for what is next. */
.tour.is-done .tour-pic {
  background: var(--ok);
  color: #ffffff;
}

.tour-title {
  margin: 0;
  font-size: var(--text-lg);
}

.tour-pitch {
  margin: 0.125rem 0 0;
  color: var(--ink-2);
  font-size: var(--text-sm);
}

.tour-progress {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.875rem 0 0.5rem;
}

progress {
  flex: 1;
  height: 0.625rem;
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: #e3e6e9;
  color: var(--ink);
  overflow: hidden;
}

progress::-webkit-progress-bar {
  background: #e3e6e9;
  border-radius: 999px;
}

progress::-webkit-progress-value {
  background: var(--ink);
  border-radius: 999px;
}

progress::-moz-progress-bar {
  background: var(--ink);
  border-radius: 999px;
}

.tour-count {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tour-steps,
.checklist {
  display: grid;
  gap: 0.25rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
  counter-reset: buoc;
}

.tour-steps li,
.checklist li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ink-2);
  font-size: var(--text-sm);
  counter-increment: buoc;
}

.tour-steps li::before,
.checklist li::before {
  content: counter(buoc);
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  font-size: var(--text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.tour-steps li.is-done,
.checklist li.is-done {
  color: var(--ink);
}

.tour-steps li.is-done::before,
.checklist li.is-done::before {
  content: "";
  border-color: var(--ok);
  background: var(--ok)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E")
    center / 0.875rem no-repeat;
}

.tour-steps li.is-now {
  color: var(--ink);
  font-weight: 700;
}

.tour-steps li.is-now::before {
  border: 2px solid var(--ink);
  background: var(--yellow);
}

.tour .actions {
  margin: 1rem 0 0;
}

/* A badge is a sign plate: the role's pictogram beside its name, as on a sign. Earned, the
   plate turns yellow with an ink rim; not yet, it stays grey with a dashed rim. */
.plates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.75rem 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.plate {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "pic name"
    "pic state";
  align-items: center;
  column-gap: 0.75rem;
  color: var(--ink-2);
}

.plate-pic {
  grid-area: pic;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 2px dashed var(--line-strong);
  border-radius: 0.375rem;
  color: var(--ink-2);
}

.plate-pic .icon {
  width: 1.75rem;
  height: 1.75rem;
}

.plate-name {
  grid-area: name;
  font-weight: 700;
  line-height: 1.25;
}

.plate-state {
  grid-area: state;
  font-size: var(--text-xs);
}

.plate.is-earned {
  color: var(--ink);
}

.plate.is-earned .plate-pic {
  border: 2px solid var(--ok);
  background: var(--ok);
  color: #ffffff;
}

.certificate {
  margin: 1rem 0;
  padding: 1.25rem;
  border-top: 3px double var(--ink);
  border-bottom: 3px double var(--ink);
  text-align: center;
}

.certificate-title {
  margin: 0 0 0.25rem;
  font-size: var(--text-h2);
  font-weight: 700;
}

/* ───────────────────────────── a guided tour ─────────────────────────────
   What the step needs pressed, and its menu item, get a yellow ring. The ring never moves
   anything: it is drawn outside the control. */

.is-guided {
  outline: 3px solid var(--ink);
  outline-offset: 5px;
  box-shadow: 0 0 0 5px var(--yellow);
}

/* A ruled section or a list in the ring gets room inside it, given back by a negative margin, so
   its words stand clear of the ring and nothing on the page moves. */
.card.is-guided,
.groups-empty.is-guided,
.has-head.is-guided,
.serial-form.is-guided {
  padding: 0.75rem;
  margin-inline: -0.75rem;
}

.step.is-guided {
  padding: 0.5rem;
}

/* In the menu the ring is drawn inside the item: the row that scrolls would cut it outside. */
.nav a.is-guided {
  outline-offset: -3px;
  box-shadow: inset 0 0 0 7px var(--yellow);
}

/* «Ở đây» sits on the ring's top edge like a label on a frame, so the eye finds what the step needs
   without reading the sign again. It is drawn by the stylesheet with an empty alternative: neither
   a screen reader nor the name of the button takes it in, since the sign already says it. It moves
   nothing: the tag stands out of the flow. The menu's ring has none; the item is the place. */
.page .is-guided {
  position: relative;
}

.page .is-guided::after {
  content: "Ở đây" / "";
  position: absolute;
  z-index: 2;
  top: -1.125rem;
  left: 0.75rem;
  padding: 0.0625rem 0.5rem;
  border-radius: 0.25rem;
  background: var(--ink);
  color: var(--yellow);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
  pointer-events: none;
}

/* ───────────────────────────── help in place ─────────────────────────────
   A word a new hire would ask about carries a press beside it that opens a short explanation. The
   box is an HTML popover, so it opens without the script; Esc or a press outside closes it. */
.head-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 0.25rem;
  margin: 0 0 0.625rem;
}

.head-hint > h1,
.head-hint > h2 {
  margin: 0;
}

.card-head .head-hint,
.page-head .head-hint {
  margin: 0;
}

.hint {
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--navy);
  cursor: pointer;
}

.hint:hover {
  background: var(--hover);
  color: var(--navy-dark);
}

.hint .icon {
  width: 1.375rem;
  height: 1.375rem;
}

.hint-box {
  width: min(28rem, calc(100vw - 2rem));
  padding: 1rem;
  border: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  background: var(--paper);
  color: var(--ink);
}

.hint-box::backdrop {
  background: rgb(20 23 26 / 0.3);
}

.hint-box p {
  max-width: 60ch;
  margin: 0 0 0.75rem;
}

.hint-box .hint-title {
  margin-bottom: 0.25rem;
  font-size: var(--text-lg);
  font-weight: 700;
}

/* ───────────────────────────── motion ───────────────────────────── */

/* Between two pages of the app the sign re-signs with a short flip, as a split-flap board does;
   everything else changes at once. The pages opt in to it in the head of base.html, where the
   browser knows it before this file has come. */
::view-transition-group(root) {
  animation-duration: 0s;
}

::view-transition-old(sign) {
  animation: 160ms cubic-bezier(0.4, 0, 1, 1) both sign-out;
}

::view-transition-new(sign) {
  animation: 220ms cubic-bezier(0.16, 1, 0.3, 1) 60ms both sign-in;
}

@keyframes sign-out {
  to {
    transform: perspective(40rem) rotateX(-70deg);
    opacity: 0;
  }
}

@keyframes sign-in {
  from {
    transform: perspective(40rem) rotateX(70deg);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after,
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
    transition: none !important;
  }
}

/* ───────────────────────────── wider screens ───────────────────────────── */

@media (min-width: 48rem) {
  .page {
    padding: 1.5rem 1.5rem 4rem;
  }

  .board {
    margin-inline: -1.5rem;
    padding-inline: 1rem;
  }

  .row-order {
    grid-template-columns: minmax(10rem, 1.2fr) minmax(0, 3fr) 9rem;
    grid-template-areas: "main axes total";
    align-items: center;
  }

  .filters {
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    align-items: end;
  }

  .tours {
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
  }
}

/* From 64rem the menu is a rail at the left, and an order's page has two columns. */
@media (min-width: 64rem) {
  :root {
    --text-h1: 1.75rem;
  }

  .has-nav .shell {
    display: grid;
    grid-template-columns: 14.5rem minmax(0, 1fr);
    align-items: start;
  }

  .has-nav .nav {
    position: sticky;
    top: 0;
    max-height: 100vh;
    overflow-y: auto;
    border-right: 1px solid var(--line);
    border-bottom: 0;
    min-height: calc(100vh - var(--bar));
  }

  .has-nav .nav ul {
    flex-direction: column;
    gap: 0.125rem;
    padding: 0.75rem 0.625rem;
    overflow-x: visible;
  }

  .has-nav .nav a {
    padding-right: 0.5rem;
  }

  .page {
    padding: 1.75rem 2rem 4rem;
  }

  .board {
    margin-inline: -2rem;
    padding-inline: 1.5rem;
  }

  .sign {
    padding: 1rem 1.25rem;
  }

  /* While a tour runs its sign stays in view, on a screen tall enough to spare the room. */
  .sign-tour {
    position: sticky;
    top: 0.75rem;
    z-index: 5;
    box-shadow: 0 6px 18px rgb(20 23 26 / 0.18);
  }

  /* An order's or a record's page: the short cards pair up in two columns, and the long ones
     (shipments, tickets, the timeline) take the whole width, so no column runs on alone below
     the fold. Read in the order of the page on a phone. */
  .detail {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(18rem, 1fr);
    gap: 0 1.5rem;
    align-items: start;
  }

  .detail > .card {
    grid-column: 1 / -1;
  }

  .detail > .pair-1a {
    grid-column: 1;
    grid-row: 1;
  }

  .detail > .pair-1b {
    grid-column: 2;
    grid-row: 1;
  }

  .detail > .next-panel,
  .detail > .next-line {
    grid-row: 2;
  }

  .detail > .pair-2a {
    grid-column: 1;
    grid-row: 3;
  }

  .detail > .pair-2b {
    grid-column: 2;
    grid-row: 3;
  }

  /* Without «Việc tiếp theo» the second pair moves up into its row. */
  .detail.no-next > .pair-2a,
  .detail.no-next > .pair-2b {
    grid-row: 2;
  }

  .detail > .pair-1a,
  .detail > .pair-1b {
    margin-top: 0;
  }
}

@media (max-height: 40rem) {
  .sign-tour {
    position: static;
    box-shadow: none;
  }
}
