/* InsideOut London — Orders.
   Modern register, per iol-brand-guidelines v2. Web apps and portals are Modern:
   hairline rules, generous air, sans throughout, serif reserved for the project name.

   Layout direction: FULL BLEED, carried over from the access app (approved 21/08/2026).
   No cards, no tinted panels — content sits on the cream page with a generous side
   margin, and hairline rules are the only dividers. Radii are 4px or none. Do not
   reintroduce a card, a tint or a 10px radius without revisiting the direction.

   Two surfaces share this sheet:
     .is-site    phone-first. Read one-handed at a site entrance, often in gloves and
                 daylight, so targets are large and contrast is high.
     .is-office  a queue worked at a desk. Denser, wider measure, table-shaped, but the
                 same tokens and the same hairlines — it must read as the same system. */

:root {
  /* v2 §3. GREEN is status only — never decorative. */
  --dark:   #3A3D40;   /* DARK   */
  --light:  #EFEAE0;   /* CREAM  — page ground, always. Never pure white. */
  --bronze: #B66A3B;   /* BRONZE */
  --mid:    #F5F0E8;   /* MID    */
  --ink:    #1A1A1A;   /* INK    */
  --muted:  #7A756D;   /* MUTED  */
  --line:   #D5CCBF;   /* HAIR   */
  --green:  #3F7A4F;   /* GREEN  — status: received */

  /* Status palette. A deliberate departure from brand v2 §3, which makes status
     colouring binary (GREEN complete / BRONZE otherwise) and forbids a third state
     colour. Approved 23/08/2026: a procurement queue is scanned, not read, and eight
     states all in bronze cannot be told apart at a glance.

     Every hue is pitched at GREEN's lightness and chroma so the set reads as one
     palette, and each is dark enough on CREAM to stay legible at the 0.66rem tracked
     size these labels use. The mapping follows the Status colours in Airtable, so the
     app and the base agree. v2 §3 should be updated to record this. */
  --st-upcoming:  #5A6878;   /* slate — planned, not yet live */
  --st-requested: #3F6A8A;   /* blue */
  --st-clarify:   #8A6817;   /* gold — waiting on site */
  --st-toorder:   #B66A3B;   /* BRONZE — needs action, the original default */
  --st-ordered:   #6B5591;   /* purple — placed, in transit */
  --st-return:    #9F4436;   /* red */

  /* Order type. Two values, so two quiet hues — they label, never shout. */
  --ty-material:  #6E5D3A;   /* olive-brown */
  --ty-supply:    #85486A;   /* plum */

  --radius: 4px;       /* Full bleed: sharp, not soft. */
  --gap:    1.35rem;
  --edge:   1.5rem;    /* The side margin the whole app hangs off. */
  --measure: 34rem;    /* Site: one column, phone-first. */
  --measure-wide: 74rem; /* Office: the queue needs the width. */

  /* v2 §4. Three faces, each with one job. Serif carries the project name and
     nothing else — the v1 rule that put it on every title is withdrawn. */
  --display: 'Bodoni Moda', Georgia, 'Times New Roman', serif;
  --body:    'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--light);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.55;
  padding-bottom: env(safe-area-inset-bottom);
}

/* The office portal is read at a desk, where 17px body on a wide measure is loose. */
body.is-office { font-size: 16px; }

/* ---------------------------------------------------------------- topbar */

/* One hairline instead of a dark band. The mark and the site name carry the
   identity; nothing else competes before the content. */
.topbar {
  padding: calc(1rem + env(safe-area-inset-top)) var(--edge) 0.8rem;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: var(--measure);
  margin: 0 auto;
}
.is-office .topbar { max-width: var(--measure-wide); }

.topbar__mark {
  flex: 0 0 auto;
  width: auto;
  height: 1.375rem;
  display: block;
  opacity: 0.9;
}

.topbar__text { flex: 1 1 auto; min-width: 0; }

.topbar__site {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The one serif in the app: the project's name, per v2 §4. */
.topbar__project {
  margin: 0;
  font-family: var(--display);
  font-size: 1.05rem;
  line-height: 1.2;
  color: var(--dark);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar__code {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bronze);
}

/* Text wordmark fallback, used only when the logo file is absent (v2 §5.1). */
.brand {
  margin: 0;
  font-family: var(--display);
  font-size: 1.15rem;
  line-height: 1;
  color: var(--dark);
}
.brand__sub {
  display: block;
  font-family: var(--mono);
  font-size: 0.55rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--bronze);
  margin-top: 0.15rem;
}

/* ----------------------------------------------------------------- shell */

.shell {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.6rem var(--edge) 3rem;
}
.is-office .shell { max-width: var(--measure-wide); }

.screen { display: none; }
.screen.is-active { display: block; }

/* --------------------------------------------------------------- headings */

/* Tracked mono small-caps: the system's signature (v2 §4). Never larger than the
   body text — at that point it stops reading as a label and starts competing. */
.eyebrow {
  margin: 0 0 0.45rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bronze);
}

/* Sans, not serif — v2 §8 withdrew serif from document titles. */
.display {
  margin: 0 0 0.7rem;
  font-size: 1.55rem;
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--dark);
}

.lede { margin: 0 0 1.5rem; color: var(--ink); }

.section-title {
  margin: 2.2rem 0 0.9rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--dark);
  font-size: 1rem;
  font-weight: 700;
  color: var(--dark);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}
.section-title__note {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--muted);
}

/* ------------------------------------------------------------------ forms */

.field { margin-bottom: var(--gap); }

.field__label {
  display: block;
  margin-bottom: 0.35rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bronze);
}

.field__hint {
  margin: 0.35rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
}

input[type=text], input[type=tel], input[type=number], input[type=date],
input[type=password], select, textarea {
  width: 100%;
  padding: 0.8rem 0.85rem;
  font-family: var(--body);
  font-size: 1.05rem;          /* 16px+ so iOS does not zoom the page on focus. */
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  appearance: none;
}
.is-office input[type=text], .is-office input[type=tel], .is-office input[type=number],
.is-office input[type=date], .is-office input[type=password], .is-office select,
.is-office textarea { font-size: 1rem; padding: 0.6rem 0.7rem; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--bronze);
  box-shadow: 0 0 0 1px var(--bronze);
}

/* Money and quantities in mono, so columns of figures line up. */
input.mono, input[type=number] { font-family: var(--mono); }

textarea { min-height: 5.5rem; resize: vertical; line-height: 1.5; }

select {
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 1.1rem) 55%, calc(100% - 0.75rem) 55%;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
  padding-right: 2.2rem;
}

/* A row of fields that share a line once there is room for it. */
.row { display: flex; flex-wrap: wrap; gap: 0 1rem; }
.row > .field { flex: 1 1 8rem; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 3.25rem;         /* Site: a gloved thumb. */
  padding: 0.85rem 1.2rem;
  font-family: var(--body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--light);
  background: var(--dark);
  border: 1px solid var(--dark);
  border-radius: var(--radius);
  cursor: pointer;
}
.btn:disabled { opacity: 0.45; cursor: default; }

.btn--ghost { color: var(--dark); background: transparent; }
.btn--bronze { background: var(--bronze); border-color: var(--bronze); }

.btn--inline {
  width: auto;
  min-height: 2.5rem;
  padding: 0.45rem 0.9rem;
  font-size: 0.88rem;
}

/* A quiet way back out of a screen. Deliberately NOT a button: two buttons stacked
   read as two choices of equal weight, and the secondary one competed with the
   primary action. Kept as a <button> element though — it performs an action rather
   than navigating, so an href-less <a> would be wrong for anyone using a keyboard
   or a screen reader. */
.textlink {
  display: inline;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  font: inherit;
  font-size: 0.9rem;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}
.textlink:hover { color: var(--bronze); }
.textlink:focus-visible { outline: 1px solid var(--bronze); outline-offset: 2px; }

/* Gives the link air beneath a full-width button instead of butting against it. */
.textlink-row { margin: 1.1rem 0 0; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.4rem; }
.btn-row > .btn { width: auto; flex: 1 1 10rem; }

/* --------------------------------------------------------------- statuses */

/* One colour per state, from the palette above. The dot carries the colour at a
   glance in a long list; the word carries the meaning. Both take currentColor, so a
   status only ever needs its one class. */
.status {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bronze);
  white-space: nowrap;
}
.status::before {
  content: '';
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: currentColor;
  margin-right: 0.4rem;
  vertical-align: 0.02em;
}

.status--upcoming  { color: var(--st-upcoming); }
.status--requested { color: var(--st-requested); }
.status--clarify   { color: var(--st-clarify); }
.status--toorder   { color: var(--st-toorder); }
.status--ordered   { color: var(--st-ordered); }
.status--received  { color: var(--green); }
.status--return    { color: var(--st-return); }

/* Closed rather than complete. Returned keeps its word; Cancelled is struck through,
   which says "dead" faster than any colour and costs no new hue. */
.status--returned  { color: var(--muted); }
.status--cancelled { color: var(--muted); text-decoration: line-through; }

/* Order type. Same tracked-mono treatment, no dot — the dot is the status's job, and
   two dots on one row would compete. */
.type {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--muted);
}
.type--material { color: var(--ty-material); }
.type--supply   { color: var(--ty-supply); }

/* Needed By in the past, or an ETA later than it. Bronze, and the words carry it. */
.late { color: var(--bronze); font-weight: 600; }

/* ------------------------------------------------------------ order rows */

/* The list is the app. Hairline-separated rows, no banding, no fills (v2 §7). */
.orders { margin: 0; padding: 0; list-style: none; }

.order {
  display: block;
  width: 100%;
  padding: 1rem 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  background: transparent;
  border-left: 0; border-right: 0; border-top: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.order:first-child { border-top: 1px solid var(--line); }

.order__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.9rem;
}

.order__ref {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--bronze);
}

.order__item {
  margin: 0.25rem 0 0;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--dark);
}

/* Qty, project, dates. Tracked mono so the row reads as a record, not a sentence. */
.order__meta {
  margin: 0.35rem 0 0;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.9rem;
}

.order__note {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
  color: var(--ink);
}

/* ------------------------------------------------------------------ tabs */

.tabs {
  display: flex;
  gap: 1.4rem;
  margin: 0 0 1.5rem;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  flex: 0 0 auto;
  padding: 0 0 0.7rem;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.tab.is-active { color: var(--dark); border-bottom-color: var(--bronze); }
.tab__count { color: var(--bronze); }

/* The filter row is the first thing on the queue page, and on a quiet day it may be
   the only thing — an empty queue has no rows to carry colour. So each tab wears its
   status colour: a dot always, and the underline when it is the live view. The label
   itself stays muted/dark, because tracked mono at 0.7rem in a mid hue is hard work
   to read. */
.tab__dot {
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--muted);
  margin-right: 0.4rem;
  vertical-align: 0.02em;
}

.tab--to-order .tab__dot { background: var(--st-toorder); }
.tab--upcoming .tab__dot { background: var(--st-upcoming); }
.tab--ordered  .tab__dot { background: var(--st-ordered); }
.tab--received .tab__dot { background: var(--green); }

.tab--to-order.is-active { border-bottom-color: var(--st-toorder); }
.tab--upcoming.is-active { border-bottom-color: var(--st-upcoming); }
.tab--ordered.is-active  { border-bottom-color: var(--st-ordered); }
.tab--received.is-active { border-bottom-color: var(--green); }

/* ----------------------------------------------------------------- detail */

/* The order the office is working. Not a modal card — a panel that replaces the list,
   so the layout stays flat and the back path is explicit. */
.detail__back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1.2rem;
  padding: 0;
  background: transparent;
  border: 0;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}

/* Label/value pairs with hairline rules and no cell fills (v2 §7). */
.facts { margin: 0 0 1.8rem; border-top: 1px solid var(--line); }
.facts__row {
  display: flex;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
}
.facts__key {
  flex: 0 0 9rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bronze);
  padding-top: 0.15rem;
}
.facts__val { flex: 1 1 auto; min-width: 0; }
.facts__val--mono { font-family: var(--mono); }

/* --------------------------------------------------------------- notices */

/* No tinted panels: a notice is a bronze left rule and text. */
.notice {
  margin: 0 0 1.4rem;
  padding: 0.15rem 0 0.15rem 0.9rem;
  border-left: 2px solid var(--bronze);
  font-size: 0.92rem;
}
.notice strong { display: block; color: var(--dark); }
.notice--ok { border-left-color: var(--green); }

.empty {
  margin: 2.5rem 0;
  color: var(--muted);
  font-size: 0.95rem;
}

/* --------------------------------------------------------------- choices */

/* Radio group that reads as a list of decisions, not a form control. */
.choice {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.choice:first-of-type { border-top: 1px solid var(--line); }
.choice input { flex: 0 0 auto; margin: 0.25rem 0 0; accent-color: var(--bronze); width: 1.1rem; height: 1.1rem; }
.choice__label { font-weight: 600; color: var(--dark); }
.choice__hint { display: block; font-weight: 400; font-size: 0.88rem; color: var(--muted); }

/* ----------------------------------------------------------------- photo */

.photo-slot { margin-bottom: var(--gap); }
.photo-slot input[type=file] { display: none; }

.photo-slot__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3.25rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.photo-slot__btn.is-set { border-style: solid; border-color: var(--green); color: var(--green); }

.photo-slot__preview {
  display: none;
  margin-top: 0.7rem;
  width: 100%;
  max-height: 14rem;
  object-fit: contain;
  border-radius: var(--radius);
}
.photo-slot__preview.is-shown { display: block; }

/* ------------------------------------------------------------------ misc */

.msg {
  margin: 1rem 0 0;
  font-size: 0.92rem;
  color: var(--bronze);
  min-height: 1.2rem;
}
.msg--ok { color: var(--green); }

.spinner { color: var(--muted); font-size: 0.92rem; }

/* Wider viewports: the office queue gains a two-column detail, site stays one. */
@media (min-width: 56rem) {
  .is-office .facts__row { gap: 1.5rem; }
  .is-office .row > .field { flex: 1 1 12rem; }
}

@media (prefers-reduced-motion: no-preference) {
  .order, .tab, .btn { transition: color 120ms ease, border-color 120ms ease, opacity 120ms ease; }
}
