/* ==========================================================================
   Ramen Haus HQ
   Dark rail + light workspace. Brand colours carried over from the
   customer-facing site so the portal reads as the same company.
   ========================================================================== */

:root {
  --orange:      #ee5007;
  --orange-dark: #c93f03;
  --yellow:      #f8cb2e;
  --cream:       #fff7ed;

  --ink:         #16130f;
  --ink-2:       #221d18;
  --ink-3:       #332b23;

  --text:        #1c1917;
  --text-muted:  #6b6259;
  --text-invert: #f7f1e8;

  --bg:          #f6f3ef;
  --surface:     #ffffff;
  --border:      #e3ddd4;
  --border-dark: #3a312a;

  --green:       #2f7d4f;
  --green-bg:    #e8f5ed;
  --red:         #b3261e;
  --red-bg:      #fdeceb;
  --amber:       #8a5a00;
  --amber-bg:    #fdf3dc;
  --blue:        #1c5d99;
  --blue-bg:     #e9f1f9;

  --radius:      10px;
  --radius-sm:   6px;
  --rail:        232px;

  --shadow-sm:   0 1px 2px rgba(28,25,23,.06);
  --shadow:      0 2px 8px rgba(28,25,23,.08);
  --shadow-lg:   0 8px 28px rgba(28,25,23,.14);

  --font: "Josefin Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

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

/* Author `display` rules outrank the UA stylesheet's [hidden] { display:none },
   so an element with display:flex stays visible when scripts set hidden.
   Everything below relies on toggling `hidden`, so make it win. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.25; font-weight: 700; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }
p  { margin: 0 0 1rem; }

a { color: var(--orange-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- layout */

.app { display: flex; min-height: 100vh; }

.rail {
  width: var(--rail);
  flex: 0 0 var(--rail);
  background: var(--ink);
  color: var(--text-invert);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.rail__brand {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: 1.15rem 1.15rem 1rem;
  border-bottom: 1px solid var(--border-dark);
}
.rail__mark {
  width: 34px; height: 34px; flex: 0 0 34px;
  display: grid; place-items: center;
  background: var(--orange);
  border-radius: 9px;
  font-size: 1.05rem;
}
.rail__name { font-weight: 700; letter-spacing: .02em; line-height: 1.15; }
.rail__sub  { font-size: .72rem; color: #a89c8e; letter-spacing: .09em; text-transform: uppercase; }

.rail__nav { padding: .5rem .6rem; overflow-y: auto; flex: 1; }
/* Spacing here is deliberately tight: the full nav plus the account footer
   has to clear a 720px-tall laptop viewport without the last item hiding
   behind the footer. */
.rail__section {
  font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  color: #7d7266; padding: .6rem .6rem .25rem; font-weight: 600;
}
.rail__link {
  display: flex; align-items: center; gap: .6rem;
  padding: .38rem .6rem;
  border-radius: var(--radius-sm);
  color: #d9cfc2;
  font-size: .9rem;
  margin-bottom: 1px;
}
.rail__link:hover { background: var(--ink-2); color: #fff; text-decoration: none; }
.rail__link.is-active { background: var(--ink-3); color: #fff; box-shadow: inset 3px 0 0 var(--orange); }
.rail__link svg { width: 17px; height: 17px; flex: 0 0 17px; opacity: .82; }

.rail__foot { border-top: 1px solid var(--border-dark); padding: .5rem .6rem .6rem; flex: 0 0 auto; }
.rail__user { display: flex; align-items: center; gap: .55rem; padding: .25rem .25rem .45rem; }
.rail__avatar {
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: 50%;
  background: var(--orange); color: #fff;
  display: grid; place-items: center;
  font-size: .76rem; font-weight: 700;
}
.rail__uname { font-size: .84rem; font-weight: 600; line-height: 1.2; }
.rail__urole { font-size: .72rem; color: #a89c8e; }

/* main column */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: none;
  align-items: center; gap: .75rem;
  background: var(--ink); color: #fff;
  padding: .6rem .9rem;
  position: sticky; top: 0; z-index: 40;
}
/* The most-tapped control in the whole portal on a phone, and it was 29px
   tall — under the threshold where a thumb hits it reliably first time. */
.topbar__burger {
  background: none; border: 1px solid #4a4038; color: #fff;
  border-radius: var(--radius-sm); padding: 0 .7rem;
  min-height: 42px; min-width: 42px;
  font-size: 1.05rem; cursor: pointer; line-height: 1;
}

.content { padding: 1.6rem 1.9rem 3rem; max-width: 1220px; width: 100%; }

.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.3rem;
}
.page-head p { margin: .15rem 0 0; color: var(--text-muted); font-size: .92rem; }

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

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.card__head {
  padding: .85rem 1.1rem;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
}
.card__head h2, .card__head h3 { margin: 0; }
.card__body { padding: 1.1rem; }

/* stat strip */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: .85rem; margin-bottom: 1.4rem; }
.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: .9rem 1rem;
}
.stat__label { font-size: .72rem; letter-spacing: .07em; text-transform: uppercase; color: var(--text-muted); font-weight: 600; }
.stat__value { font-size: 1.75rem; font-weight: 700; line-height: 1.15; margin-top: .15rem; }
.stat__note  { font-size: .78rem; color: var(--text-muted); }

/* module tiles */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: .9rem; }
.tile {
  position: relative;
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.05rem 1.05rem;
  color: inherit;
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.tile:hover { text-decoration: none; }
.tile--ready:hover { border-color: var(--orange); box-shadow: var(--shadow); transform: translateY(-1px); }
.tile__icon {
  width: 36px; height: 36px; border-radius: 9px;
  background: var(--cream); color: var(--orange-dark);
  display: grid; place-items: center; margin-bottom: .65rem;
}
.tile__icon svg { width: 19px; height: 19px; }
.tile__label { font-weight: 700; font-size: 1rem; }
.tile__desc  { font-size: .84rem; color: var(--text-muted); margin-top: .15rem; }

/* ---------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.data th {
  /* `text-align: left` here is the default for a header; the .num rule below
     overrides it for numeric columns. Both th and td must be listed, or the
     label sits left while the figures under it sit right. */
  text-align: left; font-size: .7rem; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 700;
  padding: .6rem .85rem; border-bottom: 1px solid var(--border); white-space: nowrap;
}
table.data td { padding: .68rem .85rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: #faf8f5; }
/* A numeric column aligns as one, heading included — 30 screens rely on this. */
table.data th.num,
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
.t-mono { font-family: var(--mono); font-size: .82rem; }
.t-muted { color: var(--text-muted); }
.t-sm { font-size: .82rem; }

.person { display: flex; align-items: center; gap: .6rem; }
.person__avatar {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%;
  background: var(--ink-3); color: #fff;
  display: grid; place-items: center; font-size: .74rem; font-weight: 700;
}
.person__name { font-weight: 600; line-height: 1.2; }
.person__meta { font-size: .78rem; color: var(--text-muted); }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-block; font-size: .7rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  padding: .16rem .5rem; border-radius: 999px;
  background: var(--bg); color: var(--text-muted); border: 1px solid var(--border);
  white-space: nowrap;
}
.badge--owner   { background: #f3e8ff; color: #6b21a8; border-color: #e4d1fb; }
.badge--manager { background: var(--blue-bg);  color: var(--blue);  border-color: #cfe0f0; }
.badge--lead    { background: var(--green-bg); color: var(--green); border-color: #cfe7da; }
.badge--staff   { background: var(--amber-bg); color: var(--amber); border-color: #f0e0b8; }
.badge--vendor  { background: #f0eeec; color: #5b5148; border-color: #ded8d0; }
.badge--off     { background: var(--red-bg); color: var(--red); border-color: #f5d3d1; }
.badge--ok      { background: var(--green-bg); color: var(--green); border-color: #cfe7da; }
.badge--warn    { background: var(--amber-bg); color: var(--amber); border-color: #f0e0b8; }

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

.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 1.2rem; }
.field { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.field--full { grid-column: 1 / -1; }
.field label { font-size: .82rem; font-weight: 600; }
.field .hint { font-size: .78rem; color: var(--text-muted); }
.field .err  { font-size: .8rem; color: var(--red); font-weight: 600; }

input[type=text], input[type=password], input[type=email], input[type=tel],
input[type=date], input[type=number], input[type=search], select, textarea {
  width: 100%;
  font: inherit; font-size: .92rem;
  color: var(--text);
  padding: .52rem .7rem;
  background: #fff;
  border: 1px solid #d5cec4;
  border-radius: var(--radius-sm);
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(238,80,7,.14);
}
input[aria-invalid=true], select[aria-invalid=true] { border-color: var(--red); }
textarea { min-height: 96px; resize: vertical; }
select { appearance: none; background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236b6259'%3E%3Cpath d='M4.5 6.5 8 10l3.5-3.5z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .5rem center; padding-right: 1.9rem; }

.check-row { display: flex; flex-wrap: wrap; gap: .5rem .9rem; }
.check {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .9rem; padding: .32rem .6rem;
  border: 1px solid #d5cec4; border-radius: var(--radius-sm); background: #fff;
  cursor: pointer;
}
.check input { accent-color: var(--orange); margin: 0; }
.check:hover { border-color: #bdb3a6; }

.form-actions {
  display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
  margin-top: 1.3rem; padding-top: 1.1rem; border-top: 1px solid var(--border);
}

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  font: inherit; font-size: .9rem; font-weight: 600;
  padding: .52rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--orange); color: #fff;
  cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s;
}
.btn:hover { background: var(--orange-dark); text-decoration: none; color: #fff; }
.btn:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.btn--ghost { background: #fff; color: var(--text); border-color: #d5cec4; }
.btn--ghost:hover { background: var(--bg); color: var(--text); border-color: #bdb3a6; }
.btn--danger { background: var(--red); }
.btn--danger:hover { background: #8f1e17; }
.btn--sm { font-size: .82rem; padding: .34rem .68rem; }
.btn--block { width: 100%; }
.btn[disabled] { opacity: .55; cursor: not-allowed; }

.btn-row { display: flex; gap: .4rem; flex-wrap: wrap; }
/* Row actions stay on one line — the table already scrolls horizontally,
   which reads better than a row that grows to two lines mid-list. */
table.data .btn-row { flex-wrap: nowrap; align-items: center; }
table.data .btn-row form { display: inline-flex; margin: 0; }

/* ---------------------------------------------------------------- alerts */

.alert {
  border: 1px solid var(--border); border-left-width: 3px;
  border-radius: var(--radius-sm);
  padding: .7rem .9rem; margin-bottom: 1rem; font-size: .9rem;
  /* A modifier that doesn't exist used to leave the box with no background at
     all, so an important notice read as ordinary small print — which is
     exactly how a write-up notice went unnoticed. The base now carries enough
     of a look that a mistyped modifier is still visibly an alert. */
  background: var(--cream);
  border-left-color: var(--text-muted);
}
.alert--success { background: var(--green-bg); border-color: #cfe7da; border-left-color: var(--green); color: #1e5c39; }
.alert--error   { background: var(--red-bg);   border-color: #f5d3d1; border-left-color: var(--red);   color: #8f1e17; }
.alert--warning { background: var(--amber-bg); border-color: #f0e0b8; border-left-color: var(--yellow);color: #6d4700; }
.alert--info    { background: var(--blue-bg);  border-color: #cfe0f0; border-left-color: var(--blue);  color: #164b7d; }

.empty { text-align: center; padding: 2.6rem 1rem; color: var(--text-muted); }
.empty__icon { font-size: 1.9rem; opacity: .5; }

/* ------------------------------------------------------------- filterbar */

.filterbar {
  display: flex; gap: .55rem; flex-wrap: wrap; align-items: center;
  padding: .8rem 1.1rem; border-bottom: 1px solid var(--border); background: #fbfaf8;
  border-radius: var(--radius) var(--radius) 0 0;
}
.filterbar input[type=search], .filterbar select { width: auto; min-width: 150px; }

.pager { display: flex; gap: .4rem; align-items: center; justify-content: center; padding: 1rem; }

/* ------------------------------------------------------------ auth pages */

.bare {
  min-height: 100vh;
  display: grid; place-items: center;
  padding: 1.5rem;
  background: linear-gradient(160deg, #221d18 0%, #16130f 62%, #2b1a0d 100%);
}
.authbox { width: 100%; max-width: 392px; }
.authbox__brand { text-align: center; margin-bottom: 1.4rem; color: #fff; }
.authbox__mark {
  width: 54px; height: 54px; margin: 0 auto .6rem;
  display: grid; place-items: center;
  background: var(--orange); border-radius: 14px; font-size: 1.6rem;
}
.authbox__name { font-size: 1.28rem; font-weight: 700; letter-spacing: .01em; }
.authbox__sub  { font-size: .8rem; color: #a89c8e; letter-spacing: .1em; text-transform: uppercase; }
.authbox__card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1.5rem;
  box-shadow: var(--shadow-lg);
}
.authbox__card .field + .field { margin-top: .9rem; }
.authbox__foot { text-align: center; margin-top: 1.1rem; font-size: .86rem; }
.authbox__foot a { color: #d9cfc2; }
.authbox__foot a:hover { color: #fff; }

/* --------------------------------------------------------------- errors */

.errpage { text-align: center; padding: 4rem 1.5rem; }
.errpage__code { font-size: 3.4rem; font-weight: 700; color: var(--orange); line-height: 1; }

/* ========================================================================
   Counting stock
   Portrait on a phone shows the item and a number box, nothing else. Turning
   the phone sideways crosses the width threshold and reveals supplier, last
   count and a note field on the same row — one list, not two screens.
   ======================================================================== */

.rotate-hint { margin: 0 0 1rem; }
@media (min-width: 700px) { .rotate-hint { display: none; } }

.count-group { margin-bottom: 1.2rem; overflow: hidden; }
.count-group__head {
  display: flex; align-items: baseline; gap: .6rem;
  width: 100%; padding: .7rem 1rem; margin: 0;
  border: 0; border-bottom: 1px solid var(--border);
  background: var(--surface); text-align: left; cursor: pointer;
  font: inherit; color: inherit;
  position: sticky; top: 0; z-index: 5;
}
.count-group__head:hover { background: var(--cream); }
.count-group__head .t-sm { margin-left: auto; }
.count-group__chev {
  font-size: .7rem; color: var(--text-muted);
  transition: transform .15s ease; flex: 0 0 auto;
}
.count-group__head[aria-expanded="false"] .count-group__chev { transform: rotate(-90deg); }
.count-group__head[aria-expanded="false"] { border-bottom-color: transparent; }
.count-group__head[aria-expanded="false"] + .count-group__body { display: none; }
.reduce-motion .count-group__chev { transition: none; }
.count-group__head h2 {
  margin: 0;
  font-size: .78rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-muted);
}

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

/* Narrow: item on the left, number box on the right, nothing else.
   The extra columns are laid out but hidden so the markup stays one shape. */
.ci {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "main entry";
  align-items: center;
  gap: .5rem .9rem;
  padding: .55rem 1rem;
  border-bottom: 1px solid var(--border);
}
.ci:last-child { border-bottom: 0; }

.ci__main     { grid-area: main; min-width: 0; }
.ci__entry    { grid-area: entry; display: flex; align-items: center; gap: .45rem; }
.ci__supplier { grid-area: supplier; min-width: 0; display: none; }
.ci__last     { grid-area: last; min-width: 0; display: none; font-size: .82rem;
                text-align: left; white-space: nowrap; }
.ci__note     { grid-area: note; min-width: 0; display: none; }

.ci__name {
  display: block; font-weight: 600; line-height: 1.25;
  /* A tap anywhere on the name focuses the number box next to it. */
  cursor: pointer;
}
.ci__sub { line-height: 1.3; font-size: .8rem; color: var(--text-muted); }

/* `.ci` prefix on purpose: the global input[type=number] rule is (0,1,1) and
   would otherwise beat a lone class and stretch this box to fill its column.
   On the laptop that is hidden by the fixed 196px track; on a phone the track
   is auto, so the box ate the row and the item name got what was left. */
.ci .ci__qty {
  width: 92px;
  font-size: 1.15rem;      /* large enough to read and hit at arm's length */
  font-weight: 700;
  text-align: center;
  padding: .45rem .3rem;
  font-variant-numeric: tabular-nums;
}
/* Spinners waste width and are useless on a touchscreen. */
.ci__qty::-webkit-outer-spin-button,
.ci__qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ci__qty { -moz-appearance: textfield; appearance: textfield; }
.ci__qty:not(:placeholder-shown) { border-color: var(--green); background: var(--green-bg); }

.ci__unit {
  font-size: .8rem; color: var(--text-muted);
  /* Fixed rather than content-sized, so one long unit cannot shift that row's
     columns out of step with the rest. Sized for the real units in use —
     "Pack (4lb)", "Racks", "Quart" — not for "lb". */
  width: 92px; flex: 0 0 92px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.ci__chip {
  display: inline-block;
  font-size: .74rem; color: var(--text-muted);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 999px; padding: .1rem .55rem;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ci__chip--muted { opacity: .65; }
.ci__note input { font-size: .84rem; padding: .32rem .55rem; width: 100%; }

/* A counted row tints the whole line, not just the box — easier to see how
   far down the list you've got when you glance back at a laptop screen. */
.ci.is-counted { background: #f4faf6; }

/* Phone only. The fixed 92px unit exists to keep laptop columns aligned;
   below the first tier there are no columns to align, and that width is the
   difference between "Bean sprouts" reading as two words and reading as one
   word per line. */
@container (max-width: 619px) {
  .ci__unit { width: auto; flex: 0 1 auto; max-width: none; }
  .ci .ci__qty { width: 96px; flex: 0 0 96px; }
  .ci { gap: .5rem .6rem; padding-left: .8rem; padding-right: .8rem; }
}

/* The columns appear when the ROW is wide enough, not when the window is.
   A viewport media query was wrong here: the row only ever gets the window
   minus the 232px rail, so between roughly 900px and 1130px the five-column
   layout switched on and then overflowed — which is precisely laptop width.
   A container query measures the space that actually exists. Where container
   queries are unsupported the row keeps the stacked phone layout, which is a
   perfectly good outcome rather than a broken one. */
.count-group { container-type: inline-size; }

/* A phone held sideways is about 810px — under the 860 the full table needs,
   but far wider than the stacked view. That gap meant turning the phone bought
   you nothing. This tier adds the two columns worth having mid-count: when it
   was last counted, and who supplies it. The note stays out, because a text
   box needs room to be worth typing in.
   Ordered so the number box keeps the same place on the row at every size —
   your thumb should not have to hunt for it when the phone rotates. */
@container (min-width: 620px) {
  .ci {
    grid-template-columns:
      minmax(140px, 1.6fr)   /* item */
      196px                  /* number box + unit */
      minmax(96px, 0.8fr)    /* last count */
      minmax(90px, 0.7fr);   /* supplier */
    grid-template-areas: "main entry last supplier";
    gap: .5rem 1rem;
  }
  .ci__last, .ci__supplier { display: block; }
  .ci--head { display: grid; }
}

@container (min-width: 860px) {
  .ci {
    /* Every row is its own grid container, so an `auto` track sizes to that
       row's own contents — the header's "On hand" label is narrower than a
       92px input plus its unit, and the difference pushed every later column
       out of step. Fixed here so all rows resolve identically. */
    grid-template-columns:
      minmax(150px, 1.5fr)   /* item */
      196px                  /* number box + unit */
      minmax(110px, 0.9fr)   /* supplier */
      130px                  /* last count */
      minmax(140px, 1.4fr);  /* note */
    grid-template-areas: "main entry supplier last note";
    gap: .5rem 1rem;
    padding: .5rem 1rem;
  }
  .ci__supplier, .ci__last, .ci__note { display: block; }

  /* Column labels only make sense once the columns exist. */
  .ci--head {
    padding-top: .55rem; padding-bottom: .55rem;
    font-size: .68rem; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--text-muted);
    background: #fbfaf8;
  }
  /* The label sits over the number box, not over the box plus its unit. */
  .ci--head .ci__entry { justify-content: flex-start; }
  .ci--head .ci__last, .ci--head .ci__note { text-align: left; }
  /* .ci__last sets its own size for data rows, which would otherwise beat the
     header's inherited one and leave one label larger than its siblings. */
  .ci--head .ci__last { font-size: inherit; }
}
.ci--head { display: none; }
@container (min-width: 860px) { .ci--head { display: grid; } }

/* Sticky action bar — saving shouldn't mean scrolling past 60 items. */
.savebar {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .7rem .9rem;
  margin: 1.2rem -.2rem 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 -2px 12px rgba(28,25,23,.09);
}
.savebar__count { font-size: .88rem; color: var(--text-muted); }
.savebar__count strong { color: var(--text); font-variant-numeric: tabular-nums; }

/* ========================================================================
   Training
   ======================================================================== */

.manuals { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-bottom: 1.4rem; }
@media (min-width: 860px) { .manuals { grid-template-columns: 1fr 1fr; } }
.manualcard__head { display: flex; justify-content: space-between; align-items: flex-start; gap: .75rem; }
.manualcard__head h2 { margin: 0; font-size: 1.05rem; }
.manualcard__head p { margin: .15rem 0 0; }

.progress { display: flex; align-items: center; gap: .75rem; margin-top: .8rem; }
.progress__bar {
  flex: 1; height: 8px; border-radius: 999px; background: var(--border); overflow: hidden;
}
.progress__bar i { display: block; height: 100%; background: var(--orange); transition: width .2s; }
.progress__bar.is-complete i { background: var(--green); }
.progress__label { font-size: .84rem; color: var(--text-muted); white-space: nowrap; }

.reqstatus {
  margin-top: .8rem; padding: .55rem .7rem; border-radius: var(--radius-sm);
  font-size: .86rem; border: 1px solid var(--border); background: var(--bg);
}
.reqstatus--pending  { background: var(--blue-bg);  border-color: #cfe0f0; color: var(--blue); }
.reqstatus--approved { background: var(--green-bg); border-color: #cfe7da; color: var(--green); }
.reqstatus--declined { background: var(--amber-bg); border-color: #f0e0b8; color: var(--amber); }

.training-side { display: grid; grid-template-columns: 1fr; gap: 1.2rem; }
@media (min-width: 860px) { .training-side { grid-template-columns: 1.4fr 1fr; } }

/* Sign-off list */
.signlist { list-style: none; margin: 0; padding: 0; }
.signrow {
  display: grid; grid-template-columns: 28px minmax(0,1fr) auto;
  gap: .75rem; align-items: start;
  padding: .7rem 1rem; border-bottom: 1px solid var(--border);
}
.signrow:last-child { border-bottom: 0; }
.signrow__mark {
  width: 22px; height: 22px; border-radius: 6px; margin-top: .1rem;
  border: 1.5px solid #c9c0b4; background: #fff;
  display: grid; place-items: center; font-size: .8rem; font-weight: 700; color: #fff;
}
.signrow.is-signed { background: #f6fbf8; }
.signrow.is-signed .signrow__mark { background: var(--green); border-color: var(--green); }
.signrow__text { font-weight: 600; line-height: 1.3; }
.signrow__detail, .signrow__by { margin-top: .15rem; }

/* ------------------------------------------------------------------------
   Manual line kinds: repetitions, rosters and scored weeks.
   These mirror the paper booklets, so a trainer recognises them on sight.
   ------------------------------------------------------------------------ */

/* "Do it five times" — a row of boxes that fills up. */
.reps { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; margin-top: .45rem; }
.reps__box {
  width: 22px; height: 22px; border-radius: 5px;
  border: 1.5px solid #c9c0b4; background: #fff;
  display: grid; place-items: center;
  font-size: .75rem; font-weight: 700; color: #fff;
}
.reps__box.is-done { background: var(--orange); border-color: var(--orange); }
.reps .t-sm { margin: 0 .35rem; }
.reps .inline-form { display: inline; }

/* Self-ticked rosters — the trainee's own record of what they've covered. */
.roster { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .5rem; }
.roster__form { display: inline; }
.roster__chip {
  display: inline-block; padding: .32rem .7rem; border-radius: 999px;
  border: 1px solid #d5cec4; background: #fff;
  font: inherit; font-size: .82rem; font-weight: 600; color: var(--text);
  cursor: pointer;
}
button.roster__chip:hover { border-color: var(--orange); color: var(--orange-dark); }
.roster__chip.is-on { background: var(--green-bg); border-color: var(--green); color: var(--green); }
span.roster__chip { cursor: default; }

/* Scored lines — 1-5 a week, against a written pass mark. */
.scored { margin-top: .55rem; display: flex; flex-direction: column; gap: .4rem; }
.scored__week { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.scored__label {
  min-width: 62px; font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted);
}
.scored__val {
  min-width: 26px; height: 26px; padding: 0 .35rem; border-radius: 6px;
  background: var(--ink); color: var(--text-invert);
  display: inline-grid; place-items: center;
  font-size: .85rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.scored__btn {
  width: 30px; height: 30px; border-radius: 6px;
  border: 1px solid #d5cec4; background: #fff;
  font: inherit; font-size: .85rem; font-weight: 700; color: var(--text);
  cursor: pointer;
}
.scored__btn:hover { border-color: var(--orange); background: var(--cream); color: var(--orange-dark); }
.scored__total {
  font-size: .84rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.scored__total.is-pass { color: var(--green); }
.scored__total.is-fail { color: var(--red); }
.scored__rules {
  border-left: 3px solid var(--amber); background: var(--amber-bg); color: var(--amber);
  padding: .5rem .7rem; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* Compact per-manual bars on the team screen */
.minibars { display: flex; flex-direction: column; gap: .35rem; }
.minibar {
  display: grid; grid-template-columns: minmax(90px, 1fr) 90px auto auto;
  gap: .6rem; align-items: center; color: inherit;
  padding: .3rem .45rem; margin: -.3rem -.45rem;
  border-radius: var(--radius-sm);
}
.minibar:hover { text-decoration: none; background: var(--cream); }
.minibar:hover .minibar__name { color: var(--orange-dark); }
/* This is the only route to signing somebody off, and a progress bar does not
   read as a link — least of all on a phone, where there is no hover to
   discover it with. Say so on the row itself. */
.minibar__go {
  font-size: .76rem; font-weight: 700; color: var(--orange-dark); white-space: nowrap;
}
.minibar__name { font-size: .84rem; }
.minibar__track { height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; }
.minibar__track i { display: block; height: 100%; background: var(--orange); }
.minibar__track.is-complete i { background: var(--green); }
.minibar__num { font-size: .78rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ========================================================================
   Shift reports, goals and waste
   ======================================================================== */

/* Tap targets. Big enough for a thumb, because these get used at close. */
.pillset { display: flex; gap: .45rem; flex-wrap: wrap; }
.pillset--wrap { max-width: 520px; }
.pill {
  position: relative; display: inline-flex; align-items: center;
  border: 1px solid #d5cec4; border-radius: 999px; background: #fff;
  cursor: pointer; font-size: .88rem; font-weight: 600;
}
.pill input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.pill span { padding: .45rem .95rem; border-radius: 999px; white-space: nowrap; }
.pill:hover { border-color: #bdb3a6; }
.pill input:checked + span { background: var(--orange); color: #fff; }
.pill input:focus-visible + span { outline: 2px solid var(--orange); outline-offset: 2px; }

/* Pace carries its own meaning, so it keeps its own colour when chosen. */
.pill--quiet   input:checked + span { background: #6b7f8f; }
.pill--steady  input:checked + span { background: var(--green); }
.pill--busy    input:checked + span { background: #b5760a; }
.pill--slammed input:checked + span { background: var(--red); }
.pill--flag    input:checked + span { background: var(--amber); }

.pace {
  display: inline-block; font-size: .72rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  padding: .14rem .55rem; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
}
.pace--quiet   { background: #eef2f5; color: #4a5b68; border-color: #dce4ea; }
.pace--steady  { background: var(--green-bg); color: var(--green); border-color: #cfe7da; }
.pace--busy    { background: var(--amber-bg); color: var(--amber); border-color: #f0e0b8; }
.pace--slammed { background: var(--red-bg);   color: var(--red);   border-color: #f5d3d1; }

.flagset { display: flex; flex-direction: column; gap: .5rem; }
.flagrow { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.flagrow__detail { flex: 1; min-width: 220px; font-size: .88rem; }

/* Handover blocks — shown on the dashboard and in the meeting pack. */
.handover-card { margin-bottom: 1.4rem; border-left: 3px solid var(--orange); }

/* Flags and the handover sit next to each other and are different kinds of
   thing — one is work waiting on you, the other is context. Same gap as every
   other stacked card, and its own colour so the pair does not read as one
   block split by a rule. */
.flags-card { margin-bottom: 1.4rem; border-left: 3px solid var(--amber); }
.handover + .handover { margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--border); }
.handover__meta { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; margin-bottom: .3rem; }
.handover__text { white-space: pre-wrap; line-height: 1.55; }
.handover-cell {
  max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.daymark {
  font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-muted); margin: 1.2rem 0 .5rem; padding-bottom: .25rem;
  border-bottom: 1px solid var(--border);
}
.daymark:first-child { margin-top: 0; }

/* Goals */
.goallist { display: flex; flex-direction: column; gap: .3rem; }
.goal-form { margin: 0; }
.goal {
  display: flex; align-items: flex-start; gap: .6rem; width: 100%;
  padding: .45rem .5rem; border-radius: var(--radius-sm);
  background: none; border: 0; font: inherit; text-align: left; cursor: pointer;
  color: var(--text);
}
button.goal:hover { background: var(--bg); }
.goal__box {
  flex: 0 0 20px; width: 20px; height: 20px; margin-top: .1rem;
  border: 1.5px solid #c9c0b4; border-radius: 5px;
  display: grid; place-items: center; font-size: .78rem; font-weight: 700;
  color: #fff; background: #fff;
}
.goal.is-done .goal__box { background: var(--green); border-color: var(--green); }
.goal.is-done > span:last-child { text-decoration: line-through; color: var(--text-muted); }
.goal input[type=checkbox] { accent-color: var(--orange); width: 18px; height: 18px; margin-top: .15rem; }

/* Recurring flag groups */
.flaggroup + .flaggroup { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.flaggroup__head { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; margin-bottom: .4rem; }
.flaggroup__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.flaggroup__list li { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; font-size: .9rem; }
.inline-form { display: inline-flex; gap: .35rem; align-items: center; margin: 0; flex-wrap: wrap; }
.inline-form input { font-size: .82rem; padding: .25rem .45rem; min-width: 180px; }
/* A 180px minimum plus a button is wider than a phone. Let the field take the
   row and the button drop under it rather than pushing the page sideways. */
@media (max-width: 560px) {
  .inline-form { width: 100%; }
  .inline-form input { min-width: 0; flex: 1 1 100%; }
}

/* Shout-outs */
.shout + .shout { margin-top: .8rem; padding-top: .8rem; border-top: 1px solid var(--border); }
.shout__who { display: flex; align-items: center; gap: .5rem; }
.shout__note { margin-top: .25rem; }

/* Waste logger */
.qtyrow { display: flex; align-items: center; gap: .6rem; }
.qtyrow input { font-size: 1.15rem; font-weight: 700; text-align: center; max-width: 130px; }
.qtyrow__unit { font-size: .9rem; color: var(--text-muted); }

.meeting-grid { display: grid; grid-template-columns: 1fr; gap: 1.2rem; }
@media (min-width: 900px) { .meeting-grid { grid-template-columns: 1fr 1fr; } }

/* ========================================================================
   Invoices
   ======================================================================== */

.inv-thumb {
  display: block; width: 40px; height: 40px; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--border); background: var(--bg);
}
.inv-thumb--none { display: grid; place-items: center; font-size: 1rem; opacity: .5; }

.inv-full { display: block; width: 100%; height: auto; }

.photo-preview { margin-top: .7rem; }
.photo-preview img {
  display: block; max-width: 100%; max-height: 320px;
  border-radius: var(--radius-sm); border: 1px solid var(--border);
}

/* Photo beside the lines on a wide screen; stacked on a phone, where the
   photo matters less than getting the numbers in. */
.inv-layout { display: grid; grid-template-columns: 1fr; gap: 1.2rem; }
@media (min-width: 1040px) {
  .inv-layout { grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); align-items: start; }
  .inv-photo { position: sticky; top: 1rem; }
}

.kv { display: grid; grid-template-columns: auto 1fr; gap: .35rem 1rem; margin: 0; }
.kv dt { color: var(--text-muted); font-size: .86rem; }
.kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

.inv-tbl input, .inv-tbl select { padding: .3rem .45rem; font-size: .85rem; width: 100%; }
.inv-qty  { max-width: 76px; text-align: right; }
.inv-unit { max-width: 84px; }
.inv-amt  { max-width: 96px; text-align: right; font-variant-numeric: tabular-nums; }
.inv-tbl tr.is-unmatched { background: var(--amber-bg); }
.inv-tbl select { min-width: 160px; }

/* A transcribed row is not a saved row. The stripe is there to stop anyone
   reading a screen full of pre-filled numbers as a screen full of facts. */
.inv-tbl tr.is-draft { background: var(--blue-bg); box-shadow: inset 3px 0 0 var(--blue); }

/* Five editable columns don't fit a phone; same card treatment as the
   items-and-pars editor. */
@media (max-width: 860px) {
  .inv-tbl thead { display: none; }
  .inv-tbl, .inv-tbl tbody, .inv-tbl tr, .inv-tbl td { display: block; width: 100%; }
  .inv-tbl tr {
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: .65rem .75rem; margin-bottom: .55rem; background: var(--surface);
  }
  .inv-tbl tr:hover { background: var(--surface); }
  .inv-tbl td { border: 0; padding: .2rem 0; display: flex; align-items: center; gap: .7rem; text-align: left; }
  .inv-tbl td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 74px;
    font-size: .72rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--text-muted);
  }
  .inv-qty, .inv-unit, .inv-amt { max-width: none; text-align: left; }
}

/* ========================================================================
   Cost & finance
   ======================================================================== */

/* Semantic colour, kept separate from the orange accent: green is "better",
   red is "worse", and neither means "brand". */
.is-good, .t-good { color: var(--green); }
.is-bad,  .t-bad  { color: var(--red); }

.delta { font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.delta.is-up   { color: var(--green); }
.delta.is-down { color: var(--red); }

.spark { display: block; width: 100%; height: 34px; margin-top: .35rem; color: var(--orange); opacity: .85; }

.chart-wrap { overflow-x: auto; }
.chart { display: block; width: 100%; height: 150px; min-width: 320px; }
.chart__grid { stroke: var(--border); stroke-width: 1; }
.chart__line { fill: none; stroke: var(--orange); stroke-width: 2;
               stroke-linecap: round; stroke-linejoin: round;
               vector-effect: non-scaling-stroke; }
.chart__dot  { fill: var(--orange); }
.chart-axis  { display: flex; justify-content: space-between;
               font-size: .74rem; color: var(--text-muted); margin-top: .35rem; }

/* P&L table: a label column then paired value/delta columns. */
table.pnl th[scope=row] { text-align: left; font-weight: 600; text-transform: none;
                          letter-spacing: 0; font-size: .9rem; color: var(--text);
                          white-space: normal; }
table.pnl tbody tr.pnl__section th {
  padding-top: 1rem; font-size: .7rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 700; background: #fbfaf8;
}
table.pnl tbody tr.pnl__section:hover th { background: #fbfaf8; }
table.data tr.is-empty td { opacity: .5; }

.cash { width: 96px; text-align: right; font-variant-numeric: tabular-nums; }

/* Tabs */
.tabs { display: flex; gap: .25rem; border-bottom: 1px solid var(--border);
        margin-bottom: 1.2rem; overflow-x: auto; }
.tab {
  padding: .55rem .9rem; font-size: .9rem; font-weight: 600;
  color: var(--text-muted); white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab:hover { color: var(--text); text-decoration: none; }
.tab.is-active { color: var(--orange-dark); border-bottom-color: var(--orange); }

/* ---- items & par levels ---- */
.stock-tbl input[type=number], .stock-tbl input[type=text], .stock-tbl select {
  padding: .3rem .45rem; font-size: .85rem;
}
.stock-par  { width: 84px; text-align: right; font-variant-numeric: tabular-nums; }
.stock-unit { width: 92px; }
.stock-tbl select { min-width: 130px; }
.stock-tbl tr.is-inactive td { opacity: .5; }
.stock-tbl input[type=checkbox] { accent-color: var(--orange); width: 17px; height: 17px; }
.stock-active { text-align: center; }

/* Six editable columns don't survive a phone: below this width each row
   becomes its own card with labelled fields, rather than a table that has to
   be scrolled sideways to reach Supplier and Active. */
@media (max-width: 760px) {
  .stock-tbl thead { display: none; }
  .stock-tbl, .stock-tbl tbody, .stock-tbl tr, .stock-tbl td { display: block; width: 100%; }
  .stock-tbl tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: .7rem .8rem .8rem;
    margin-bottom: .6rem;
    background: var(--surface);
  }
  .stock-tbl tr:hover { background: var(--surface); }
  .stock-tbl td {
    border: 0; padding: .22rem 0;
    display: flex; align-items: center; gap: .7rem;
    text-align: left;
  }
  .stock-tbl td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 78px;
    font-size: .72rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--text-muted);
  }
  .stock-item { padding-bottom: .5rem !important; margin-bottom: .35rem;
                border-bottom: 1px solid var(--border) !important; display: block !important; }
  .stock-par, .stock-unit, .stock-tbl select { width: 100%; min-width: 0; }
  .stock-par { text-align: left; }
  .stock-active { justify-content: flex-start; }
  /* The card layout already fits, so the scroll container must not clip it. */
  .card .table-wrap:has(.stock-tbl) { overflow-x: visible; }
  .stock-tbl { border-collapse: separate; }
}

/* ========================================================================
   Vendor portal
   No rail, lighter chrome, and one obvious choice per line.
   ======================================================================== */

.vendor-body { background: var(--bg); }

.vbar { background: var(--ink); color: var(--text-invert); }
.vbar__inner {
  max-width: 900px; margin: 0 auto;
  padding: .8rem 1.1rem;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.vbar__brand { display: flex; align-items: center; gap: .6rem; }
.vbar__mark {
  width: 32px; height: 32px; border-radius: 9px; background: var(--orange);
  display: grid; place-items: center; font-size: 1rem;
}
.vbar__name { display: block; font-weight: 700; line-height: 1.15; }
.vbar__sub  { display: block; font-size: .72rem; letter-spacing: .09em; text-transform: uppercase; color: #a89c8e; }
.vbar__who  { display: flex; align-items: center; gap: .7rem; color: #d9cfc2; }

.vmain { max-width: 900px; margin: 0 auto; padding: 1.6rem 1.1rem 3rem; }
.vfoot {
  max-width: 900px; margin: 0 auto; padding: 0 1.1rem 3rem;
  color: var(--text-muted); font-size: .82rem;
}

.vlines { list-style: none; margin: 0; padding: 0; }
.vline { padding: .75rem .9rem; border-bottom: 1px solid var(--border); }
.vline:last-child { border-bottom: 0; }
.vline--flagged { background: var(--amber-bg); }

.vline__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .9rem; flex-wrap: wrap;
}
.vline__item { min-width: 0; }
.vline__name { font-weight: 600; line-height: 1.25; }
.vline__qty  { font-size: .84rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.vline__choices { display: flex; gap: .35rem; flex-wrap: wrap; }
.vchoice {
  position: relative;
  display: inline-flex; align-items: center;
  font-size: .82rem; font-weight: 600;
  border: 1px solid #d5cec4; border-radius: 999px;
  background: #fff; cursor: pointer;
}
.vchoice input {
  position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer;
}
.vchoice span { padding: .32rem .7rem; border-radius: 999px; white-space: nowrap; }
.vchoice:hover { border-color: #bdb3a6; }
.vchoice input:checked + span { background: var(--orange); color: #fff; }
.vchoice input:focus-visible + span { outline: 2px solid var(--orange); outline-offset: 2px; }

.vline__extra {
  display: flex; gap: .7rem; flex-wrap: wrap; align-items: flex-end;
  margin-top: .6rem;
}
.vline__qtyfield, .vline__notefield { display: flex; flex-direction: column; gap: .2rem; }
.vline__qtyfield { width: 140px; }
.vline__notefield { flex: 1; min-width: 200px; }

/* ------------------------------------------------------------ responsive */

@media (max-width: 900px) {
  .rail {
    position: fixed; z-index: 50; left: 0; top: 0;
    transform: translateX(-100%);
    transition: transform .18s ease;
    box-shadow: var(--shadow-lg);
  }
  .rail.is-open { transform: none; }
  .topbar { display: flex; }
  .content { padding: 1.1rem 1rem 2.5rem; }
  .form-grid { grid-template-columns: 1fr; }
  .scrim {
    position: fixed; inset: 0; background: rgba(22,19,15,.5); z-index: 45;
  }
}

@media (max-width: 560px) {
  .page-head { flex-direction: column; align-items: stretch; }
  .stat__value { font-size: 1.45rem; }
}

@media print {
  .rail, .topbar, .form-actions, .filterbar { display: none !important; }
  .content { padding: 0; max-width: none; }
  .card { border: 0; box-shadow: none; }
}


/* ========================================================================
   Courseware
   ======================================================================== */

.slide { max-width: 720px; }
.slide__body {
  font-size: 1.02rem; line-height: 1.65;
  white-space: pre-wrap; word-break: break-word;
}
.slide__body p + p { margin-top: .8rem; }

/* A question is one choice at a time — no partial credit, no guessing on. */
.quiz { margin-top: 1rem; }
.quiz form { display: flex; flex-direction: column; gap: .5rem; }
.quiz__option { position: relative; display: block; }
.quiz__option input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.quiz__option span {
  display: block; padding: .7rem .9rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface);
  font-weight: 600; cursor: pointer;
}
.quiz__option:hover span { border-color: var(--orange); background: var(--cream); }
.quiz__option input:checked + span { border-color: var(--orange); background: var(--cream); }
.quiz__option input:focus-visible + span { outline: 2px solid var(--orange); outline-offset: 2px; }

/* Authoring: one answer row, with the "this one's right" pick beside it. */
.answerrow { display: flex; align-items: center; gap: .6rem; margin-top: .5rem; }
.answerrow input[type="text"] { flex: 1; min-width: 0; }
.answerrow__pick {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted); white-space: nowrap; cursor: pointer;
}
.answerrow__pick input { margin: 0; }

@media (max-width: 560px) {
  .answerrow { flex-wrap: wrap; }
  .scored__week { gap: .35rem; }
  .scored__label { min-width: 100%; }
}

/* ========================================================================
   Reviews
   ======================================================================== */

.stars { letter-spacing: .06em; color: var(--yellow); font-size: .95rem; }
.stars i { color: #d8d2c8; font-style: normal; }

.ratingbars { display: flex; flex-direction: column; gap: .35rem; }
.ratingbar { display: grid; grid-template-columns: 34px 1fr 46px; gap: .6rem; align-items: center; }
.ratingbar__label { font-size: .8rem; font-weight: 700; color: var(--text-muted); }
.ratingbar__track { height: 8px; border-radius: 999px; background: var(--border); overflow: hidden; }
.ratingbar__track i { display: block; height: 100%; background: var(--orange); }
.ratingbar__track i.is-good { background: var(--green); }
.ratingbar__track i.is-mid  { background: var(--yellow); }
.ratingbar__track i.is-bad  { background: var(--red); }
.ratingbar__num {
  font-size: .8rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums; text-align: right;
}

.reviewcard { display: block; color: inherit; margin-bottom: .8rem; }
.reviewcard:hover { text-decoration: none; border-color: var(--orange); }
.reviewcard.is-overdue { border-left: 3px solid var(--red); }
.reviewcard__head {
  display: flex; justify-content: space-between; gap: .8rem;
  align-items: flex-start; flex-wrap: wrap; margin-bottom: .5rem;
}
.reviewcard__tags { display: flex; gap: .35rem; flex-wrap: wrap; }
.reviewcard__body { margin: 0; font-size: .92rem; line-height: 1.55; }

/* Small labelled figures, used on a removal case. */
.stat-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: .8rem; margin-top: .4rem;
}
.stat-row > div { font-size: .92rem; font-variant-numeric: tabular-nums; }

/* Count freshness on the location picker. The question a manager arriving
   mid-shift is actually asking is "has this been done", so it gets a badge
   rather than a line of prose. */
.countflag {
  display: inline-block; margin-top: .5rem;
  font-size: .7rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  border-radius: 999px; padding: .12rem .55rem;
  background: var(--bg); color: var(--text-muted); border: 1px solid var(--border);
}
.countflag.is-fresh { background: var(--green-bg); color: var(--green); border-color: transparent; }
.countflag.is-stale { background: var(--amber-bg); color: var(--amber); border-color: transparent; }

/* The count sheet's "only what needs counting" filter. */
.countfilter {
  display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: .35rem;
  margin: 0 0 1rem; padding: .5rem .8rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: .9rem;
  line-height: 1.5;
}
.countfilter input { align-self: center; }
@media (max-width: 620px) {
  /* One sentence that wraps, not three columns of ragged text. */
  .countfilter { display: block; }
  .countfilter input { float: left; margin: .25rem .5rem 0 0; }
}
/* A row nobody has counted in days earns a tint, so a long list can be
   skimmed without reading every date. */
.ci.is-stale { background: #fffdf6; }
.ci.is-stale.is-counted { background: #f6fbf8; }

/* A shortfall already covered by an order in transit. */
.ok { color: var(--green); font-weight: 700; }

/* A shopping run is filled in one-handed, in an aisle, holding a trolley. */
.runrow__inputs { display: flex; gap: .5rem; }
.runrow__field { display: flex; flex-direction: column; gap: .15rem; }
.runrow__field span {
  font-size: .66rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted);
}
.runrow__field input {
  width: 86px; padding: .5rem .45rem; text-align: center;
  font-size: 1.02rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
.runrow__field input:not(:placeholder-shown) { border-color: var(--green); background: var(--green-bg); }
@media (max-width: 560px) {
  .runrow { grid-template-columns: 22px minmax(0,1fr); }
  .runrow__inputs { grid-column: 1 / -1; margin-left: 1.35rem; }
}

/* --------------------------------------------------- waiting for something

   Three waits are long enough that silence reads as a broken page: sending a
   camera photo over the restaurant's wifi, having that photo read, and any
   POST that happens to be slow. All three get told. */

.spinner {
  display: inline-block; width: .85em; height: .85em; flex: 0 0 auto;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; vertical-align: -.1em;
  animation: spin .7s linear infinite;
}
.spinner--lg { width: 1.6rem; height: 1.6rem; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* A button mid-flight is disabled, so it must not also look inert. Needs to
   outrank .btn[disabled] above, which would otherwise fade the one control
   the person is watching. */
.btn[aria-busy="true"][disabled] { opacity: 1; cursor: progress; }

/* Determinate, because an upload is the one wait we can actually measure. */
.upload-bar {
  position: relative; margin-top: .55rem; height: 1.55rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg); overflow: hidden;
}
.upload-bar i {
  display: block; height: 100%; width: 0;
  background: linear-gradient(var(--green-bg), #d5ebde);
  border-right: 2px solid var(--green); transition: width .18s ease-out;
}
.upload-bar__label {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; font-size: .76rem; font-weight: 600;
  color: var(--text); font-variant-numeric: tabular-nums;
}

/* Indeterminate: there is nothing to measure while the model reads. The
   elapsed count does the reassuring instead. */
.busy-overlay {
  position: fixed; inset: 0; z-index: 90; display: flex;
  align-items: center; justify-content: center; padding: 1.5rem;
  background: rgba(22, 19, 15, .55);
  animation: fade .18s ease-out;
}
@keyframes fade { from { opacity: 0; } }
.busy-overlay__card {
  display: flex; flex-direction: column; align-items: center; gap: .7rem;
  max-width: 21rem; padding: 1.7rem 1.9rem; text-align: center;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}
.busy-overlay__msg  { margin: 0; font-weight: 600; }
.busy-overlay__note { margin: 0; font-size: .84rem; color: var(--text-muted); }
.busy-overlay__secs { font-variant-numeric: tabular-nums; }

.reduce-motion .spinner { animation-duration: 2.4s; }
.reduce-motion .upload-bar i { transition: none; }
.reduce-motion .busy-overlay { animation: none; }

/* A multi-page invoice: each sheet stacked, labelled and individually
   removable, because a mis-shot page should not cost you the whole capture. */
.inv-page + .inv-page { border-top: 1px solid var(--border); }
.inv-page__bar {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .45rem .9rem; background: var(--bg);
  font-size: .78rem; font-weight: 600; color: var(--text-muted);
}
.photo-preview [data-preview-extra] { margin-top: .5rem; }

/* An open flag on the dashboard. Deliberately not the sign-off tick: nothing
   here is being ticked, and an empty box invites a click that does nothing. */
.flagrow__mark {
  width: 22px; height: 22px; flex: 0 0 22px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--amber-bg); color: var(--amber);
  font-weight: 700; font-size: .85rem;
}

/* The read-only twin of the status picker, for the leadership review.
   Same colours as the control on the Tasks page: a status should look the
   same wherever it is read, or people learn two vocabularies for one idea. */
.taskchip {
  display: inline-block; white-space: nowrap;
  font-size: .8rem; font-weight: 600; padding: .25rem .7rem;
  border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-muted);
}
.taskchip--working { color: var(--blue);  background: var(--blue-bg);  border-color: #cfe0f0; }
.taskchip--blocked { color: var(--red);   background: var(--red-bg);   border-color: #f5d3d1; }
.taskchip--done    { color: var(--green); background: var(--green-bg); border-color: #cfe7da; }

/* A task you tick. Big enough for a thumb, and it is a real button so the
   whole row does not become a click target by accident. */
.taskbox {
  width: 24px; height: 24px; flex: 0 0 24px; padding: 0;
  display: grid; place-items: center;
  border: 1.5px solid var(--border); border-radius: 6px;
  background: var(--surface); cursor: pointer;
  font-size: .85rem; font-weight: 700; color: var(--green);
  transition: border-color .12s, background .12s;
}
.taskbox:hover { border-color: var(--green); background: var(--green-bg); }
.is-signed .taskbox { border-color: var(--green); background: var(--green-bg); }
.reduce-motion .taskbox { transition: none; }

/* Task rows carry a state, so the row reads at a glance and the control sits
   at the end rather than pretending to be a tickbox. */
/* A task row has no sign-off tick, so it is two columns rather than three.
   Without this the body lands in the 28px marker column and every title
   wraps one word per line. */
.signrow--task {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: flex-start;
}
/* Done rows keep the tick, so they stay three columns — marker, body, chip. */
.signrow--done { align-items: flex-start; }
@media (max-width: 620px) {
  .signrow--done { grid-template-columns: 28px minmax(0, 1fr); }
  .signrow--done .taskchip { grid-column: 2; justify-self: start; margin-top: .4rem; }
}
.taskstate { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-left: auto; }
.taskstate__pick {
  font-size: .8rem; font-weight: 600; padding: .25rem .5rem;
  min-height: 36px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
}
.taskstate__pick--new     { color: var(--text-muted); }
.taskstate__pick--working { color: var(--blue);  background: var(--blue-bg);  border-color: #cfe0f0; }
.taskstate__pick--blocked { color: var(--red);   background: var(--red-bg);   border-color: #f5d3d1; }
.taskstate__pick--done    { color: var(--green); background: var(--green-bg); border-color: #cfe7da; }
.taskstate input[type="text"] { font-size: .8rem; padding: .25rem .45rem; max-width: 190px; }
.signrow--task.is-blocked { background: var(--red-bg); }
.signrow--task.is-working { background: var(--blue-bg); }
@media (max-width: 620px) {
  /* One column, or the full-width control starves the title beside it and
     every word wraps onto its own line — worst on a blocked row, which has
     a picker, a reason box and a Save button to fit. */
  .signrow--task { grid-template-columns: minmax(0, 1fr); }
  .taskstate { margin-left: 0; width: 100%; margin-top: .5rem; }
  .taskstate__pick { flex: 1 1 auto; min-height: 42px; }
  .taskstate input[type="text"] { flex: 1 1 100%; max-width: none; min-height: 38px; }
}

/* "Splits into" on Items & Pars: how many of the smaller thing are in one
   counting unit, and what that thing is called. Both or neither. */
.packsplit { display: flex; gap: .35rem; }
.packsplit__n { width: 72px; text-align: center; }
.packsplit__u { min-width: 0; flex: 1 1 auto; }

/* Cases or packs on the waste form. */
.unitpick { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; margin-top: .5rem; }
.unitpick .hint { flex: 1 1 100%; }

/* Flags, opened up. Collapsed by default so the review stays a page rather
   than a transcript, but one click from "4 equipment flags" to what they
   actually were and how each was dealt with. */
.flagdetail { border-top: 1px solid var(--border); }
.flagdetail > summary {
  padding: .6rem 1.1rem; cursor: pointer; font-weight: 600; font-size: .92rem;
  list-style: none;
}
.flagdetail > summary::-webkit-details-marker { display: none; }
.flagdetail > summary::before { content: "▸ "; color: var(--text-muted); }
.flagdetail[open] > summary::before { content: "▾ "; }
.flagdetail > summary:hover { background: var(--cream); }
.flagdetail .signlist { border-top: 1px solid var(--border); }

/* --------------------------------------------------- search as you type */

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

/* Results being re-fetched: dim, but never collapse. A list that changes
   height while somebody is reading it moves the row out from under them. */
[data-live-search] ~ * [aria-busy="true"],
#pricebook[aria-busy="true"], #userlist[aria-busy="true"],
#applicants[aria-busy="true"], #customerlist[aria-busy="true"],
#equiplist[aria-busy="true"], #venuelist[aria-busy="true"],
#reviewlist[aria-busy="true"] {
  opacity: .55;
  transition: opacity .12s ease-out;
}

/* With the button gone the box should look like the whole control. */
.inline-form.is-live input[type="search"],
.filterbar.is-live input[type="search"] { min-width: 16rem; }

/* ------------------------------------------------------- course slide media */

/* Full-bleed across the card, capped so a tall photo can't push the text
   off the screen on a phone held upright. */
.slide__img {
  display: block;
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
  background: var(--cream);
  border-radius: var(--radius) var(--radius) 0 0;
}
.slide__figure { margin: 0; }
.slide__caption { margin: 0; padding: .6rem 1.1rem 0; }

/* 16:9 that holds its shape before the iframe loads, so the text below
   doesn't jump once it does. */
.slide__video {
  position: relative;
  aspect-ratio: 16 / 9;
  margin-bottom: 1rem;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #000;
}
.slide__video iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%; border: 0;
}

/* The editor's current-picture row. */
.slideimg__edit {
  display: flex; align-items: center; gap: .8rem;
  margin-bottom: .6rem; flex-wrap: wrap;
}
.slideimg__thumb {
  width: 120px; height: 90px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--line);
}

/* Course cover on the card, and a module's thumbnail in the list. */
.coursecard__img {
  display: block; width: 100%; height: 132px; object-fit: cover;
  border-radius: var(--radius) var(--radius) 0 0; background: var(--cream);
}
.modulethumb {
  width: 56px; height: 42px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--line);
}
/* .signrow is a fixed three-column grid. A row carrying a thumbnail needs a
   fourth track declared, or the action on the right wraps to its own line —
   which is precisely how this grid has broken before. */
.signrow--thumb { grid-template-columns: 28px 56px minmax(0, 1fr) auto; }
@container (max-width: 520px) {
  .signrow--thumb { grid-template-columns: 28px minmax(0, 1fr) auto; }
  .signrow--thumb .modulethumb { display: none; }
}

/* A withdrawn write-up: whose words are whose. */
.voided__head { margin-bottom: .4rem; }
.voided__reason {
  margin: 0 0 .5rem; padding: .4rem 0 .4rem .7rem;
  border-left: 2px solid currentColor;
  font-style: italic;
}
.voided__note { margin: 0; font-size: .85rem; opacity: .8; }

/* A card that is asking the person for something, not just reporting. */
.card--attention {
  border-color: #f0e0b8;
  border-left: 3px solid var(--yellow);
}

/* A "done"/"assign" control that opens its form in place, so a due list stays
   a list until somebody acts on a row. */
.donedrop { position: relative; }
.donedrop > summary { list-style: none; cursor: pointer; }
.donedrop > summary::-webkit-details-marker { display: none; }
.donedrop__form {
  position: absolute; right: 0; z-index: 30; width: min(20rem, 78vw);
  margin-top: .4rem; padding: .8rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 10px 30px rgba(0,0,0,.14);
  text-align: left;
}
.donedrop__form .field { margin-bottom: .5rem; }
@media (max-width: 640px) {
  .donedrop__form { position: static; width: auto; box-shadow: none; }
}

/* Choosing who goes on a shopping run, beside the button that raises it.
   The label must not wrap to two lines — "Who's / going" stacked above a
   full-width select was what made this look broken on a laptop. */
.runform { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; justify-content: flex-end; }
.runwho { display: inline-flex; align-items: center; gap: .45rem; }
.runwho__label { white-space: nowrap; }
.runwho__pick {
  width: auto; min-width: 11rem; max-width: 14rem;
  padding: .38rem 1.7rem .38rem .55rem;
  font-size: .86rem;
}
@media (max-width: 720px) {
  /* Stacked, full width, in the order somebody does it: choose, then go.
     The header itself has to wrap too, or the form is squeezed into whatever
     is left beside the supplier's name and spills off the right of the phone. */
  .card__head { flex-wrap: wrap; }
  .runform { flex-direction: column; align-items: stretch; width: 100%; min-width: 0; }
  .runwho { display: grid; grid-template-columns: auto minmax(0, 1fr); }
  .runwho__pick { width: 100%; min-width: 0; max-width: none; }
}

/* ============================================================== messages
   Two panes on a laptop, one at a time on a phone. The thread scrolls
   inside its own box so the composer stays put and the page itself never
   moves — on a phone, a send that scrolls the whole page loses your place. */

.msgwrap { display: grid; grid-template-columns: 17rem minmax(0, 1fr); gap: 1.2rem; }

.msgside { min-width: 0; }
.msgmain { min-width: 0; }

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

.conv {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .55rem .9rem; color: inherit; text-decoration: none;
  border-left: 3px solid transparent; font-size: .95rem;
}
.conv:hover { background: var(--bg); }
.conv.is-on { background: var(--bg); border-left-color: var(--orange); font-weight: 600; }
.conv__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv--empty { display: block; border-left: 0; }

.conv__count {
  background: var(--orange); color: var(--text-invert);
  border-radius: 999px; padding: 0 .45rem; min-width: 1.35rem;
  text-align: center; font-size: .78rem; font-weight: 600;
  font-variant-numeric: tabular-nums; flex: none;
}

.msgcard { display: flex; flex-direction: column; }

.thread {
  overflow-y: auto;
  /* Tall enough to hold a conversation, short enough that the composer is
     always on screen without scrolling the page. */
  height: clamp(20rem, 58vh, 34rem);
  padding: .8rem 1.1rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  overscroll-behavior: contain;
}

.msglist { list-style: none; margin: 0; padding: 0; display: flex;
           flex-direction: column; gap: .8rem; }

.msg { max-width: 46rem; }
.msg__meta { display: flex; align-items: baseline; gap: .45rem; flex-wrap: wrap; }
.msg__body { white-space: pre-wrap; overflow-wrap: anywhere; margin-top: .1rem; }

/* Your own messages are tinted rather than shoved to the right: at a glance
   you want to find who said something, not who was talking to whom. */
.msg--mine .msg__body {
  background: var(--blue-bg); border-radius: var(--radius-sm);
  padding: .35rem .6rem; display: inline-block;
}

.msg__pull { display: inline; }
.linkish {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--text-muted); text-decoration: underline; font: inherit;
}
.linkish:hover { color: var(--red); }

.sendbar form { display: flex; gap: .6rem; align-items: flex-end; }
.sendbar textarea {
  flex: 1 1 auto; min-height: 2.6rem; max-height: 10rem;
  resize: vertical; font: inherit; line-height: 1.45;
}

.note-inline {
  margin-top: .9rem; padding: .7rem .9rem;
  background: var(--amber-bg); border-left: 3px solid var(--amber);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.lede { color: var(--text-muted); }

@media (max-width: 60rem) {
  /* One pane at a time. Opening a conversation hides the list, and the back
     link at the top of the thread brings it back. */
  .msgwrap { grid-template-columns: minmax(0, 1fr); }
  .msgwrap.has-open .msgside { display: none; }
  .thread { height: clamp(16rem, 52vh, 26rem); }
  .sendbar form { flex-direction: column; align-items: stretch; }
  .sendbar .btn { width: 100%; }
}

/* Only needed when the list is hidden, which is only on a narrow screen. */
.backtolist { display: none; align-items: center; gap: .3rem; margin-bottom: .2rem; }
@media (max-width: 60rem) { .backtolist { display: inline-flex; } }

/* What the browser reports about itself, on the notifications page. */
.diag { margin-top: .7rem; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.diagrow { display: flex; justify-content: space-between; gap: 1rem;
           padding: .4rem .7rem; font-size: .86rem; }
.diagrow + .diagrow { border-top: 1px solid var(--border); }
.diagrow strong { font-weight: 600; }

/* Right-aligned cell, for the action column at the end of a table row. */
.t-right { text-align: right; }

/* Managing a channel: the list carries the weight, the controls sit beside it.
   The opposite way round from the messages page, where the list is the rail. */
.adminwrap { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: 1.2rem;
             align-items: start; }
@media (max-width: 60rem) { .adminwrap { grid-template-columns: minmax(0, 1fr); } }

/* Who holds a shopping run, and the controls to change that. */
.runowner { display: flex; justify-content: space-between; align-items: center;
            gap: 1rem; flex-wrap: wrap; }
.runowner__acts { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
@media (max-width: 40rem) {
  .runowner, .runowner__acts { width: 100%; }
  .runowner__acts { flex-direction: column; align-items: stretch; }
  .runowner__acts .btn { width: 100%; }
}

/* ------------------------------------------------------------------------
   Agreements.
   The wording sits in its own scrolling pane rather than running down the
   page, so the sign button stays where the reader can see it and reaching
   the bottom of the text is an act rather than an accident.
   ------------------------------------------------------------------------ */
.doc {
  max-height: 26rem; overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: #fdfcfa; padding: 1rem 1.15rem;
  /* The body is stored and hashed as plain text; pre-wrap is what makes the
     page show exactly what was hashed, blank lines and all. */
  white-space: pre-wrap; word-break: break-word;
  font-size: .93rem; line-height: 1.6;
}
.doc:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
/* On the signed copy there is nothing below to protect, so let it run. */
.doc--full { max-height: none; overflow-y: visible; }

/* The confirmation itself. Wide text beside a checkbox, not a chip. */
.agree { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .65rem;
         align-items: start; line-height: 1.5; font-size: .93rem; }
.agree input { accent-color: var(--orange); margin: .25rem 0 0; }
.agree input:disabled { cursor: not-allowed; }

/* Disabled until the pane has been read to the end. Visibly off rather than
   silently inert, or the first thing anyone does is click it twice. */
#signbtn:disabled { opacity: .5; cursor: not-allowed; }
/* The hint under the agreement pane. Sits close enough to read as belonging
   to it, but not touching. */
.hint--under { margin: .5rem 0 0; }

/* ------------------------------------------------------------------------
   Appealing a write-up.
   Their words and the manager's answer are both quoted rather than run into
   the surrounding prose, so you can always tell whose sentence you are
   reading — the same reason the withdrawal reason is a blockquote.
   ------------------------------------------------------------------------ */
.appeal + .appeal { margin-top: 1.4rem; padding-top: 1.4rem; border-top: 1px solid var(--border); }
.appeal__head { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.appeal__words {
  margin: .6rem 0 0; padding: .55rem .9rem;
  border-left: 3px solid var(--border); background: #fbfaf8;
  white-space: pre-wrap; word-break: break-word;
  font-size: .93rem; line-height: 1.55;
}
.appeal__decision { margin-top: .9rem; font-size: .9rem; }

/* Thumbnails of whatever they photographed. Small on purpose: this is medical
   material and it should not be sitting open across a manager's screen in a
   room with other people in it. */
.appeal__proof { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .7rem; }
.appeal__proof img {
  width: 84px; height: 84px; object-fit: cover;
  border: 1px solid var(--border); border-radius: var(--radius-sm); display: block;
}
.appeal__proof a:focus-visible img { outline: 2px solid var(--orange); outline-offset: 2px; }

/* ------------------------------------------------------------------------
   Culinary Experiences — the pages customers see.
   Same tokens as the portal so there is one design system, but a wholly
   different shell: no rail, no admin chrome, and a page that centres and
   breathes rather than filling a workspace.
   ------------------------------------------------------------------------ */
.pub { background: var(--bg); color: var(--text); }
.pub__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  padding: .9rem 1.2rem; background: var(--ink); color: var(--text-invert);
}
.pub__brand { display: inline-flex; align-items: center; gap: .55rem;
              color: inherit; font-weight: 700; font-size: 1.05rem; }
.pub__brand:hover { text-decoration: none; }
.pub__mark { font-size: 1.3rem; }
.pub__nav { display: flex; gap: 1rem; font-size: .9rem; }
.pub__nav a { color: #d9cfc2; }
.pub__nav a:hover { color: #fff; }

.pub__main { max-width: 46rem; margin: 0 auto; padding: 1.6rem 1.2rem 3rem; }
.pub__foot { max-width: 46rem; margin: 0 auto; padding: 0 1.2rem 2.5rem;
             display: flex; gap: .6rem; font-size: .85rem; color: var(--text-muted); }

/* The banner. Full bleed of the content column, and a fixed ratio so a
   portrait phone snap and a wide one both sit the same way. */
.pub__heroimg {
  width: 100%; aspect-ratio: 21 / 9; object-fit: cover; display: block;
  border-radius: var(--radius); margin-bottom: 1.4rem;
}
.pub__hero { margin-bottom: 1.6rem; }
.pub__intro { margin-top: .6rem; white-space: pre-wrap; line-height: 1.7; font-size: 1.02rem; }
.pub__sub { margin: 2rem 0 1rem; font-size: 1.25rem; }

/* What to expect. Answers to the four questions people ask before booking, so
   they read as a set rather than a paragraph somebody has to mine. */
.points {
  list-style: none; margin: 0 0 2rem; padding: 0;
  /* Four across on a 46rem column, which is what the strip is for — three
     and one stranded on a second row reads as a mistake. Wraps to two, then
     one, as the screen narrows. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: .8rem;
}
.point {
  display: grid; gap: .25rem; align-content: start;
  padding: .9rem 1rem; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
}
.point strong { font-size: .95rem; }
.point span   { font-size: .88rem; color: var(--text-muted); line-height: 1.5; }
.pub__hero h1 { margin: 0 0 .4rem; font-size: 1.9rem; line-height: 1.15; text-wrap: balance; }
.pub__hero p  { margin: 0; color: var(--text-muted); font-size: 1.02rem; line-height: 1.6; }
.pub__hero--ok h1 { color: var(--green); }
.pub__back { margin: 0 0 1rem; font-size: .88rem; }
.pub__after { margin-top: 1.2rem; font-size: .88rem; color: var(--text-muted); }

/* The list of what we run. */
.explist { display: grid; gap: 1.2rem; }
.expcard { background: var(--surface); border: 1px solid var(--border);
           border-radius: var(--radius); overflow: hidden; }
.expcard__img { width: 100%; height: 190px; object-fit: cover; display: block; }
.expcard__body { padding: 1.1rem 1.2rem 1.3rem; }
.expcard h2 { margin: 0 0 .35rem; font-size: 1.25rem; }
.expcard__sum  { margin: 0 0 .6rem; line-height: 1.55; }
.expcard__meta { margin: 0 0 .5rem; font-size: .88rem; color: var(--text-muted); }
.expcard__next { margin: 0 0 .9rem; font-size: .92rem; }

/* One experience in full. */
.expfull__img { width: 100%; max-height: 340px; object-fit: cover;
                border-radius: var(--radius); display: block; margin-bottom: 1.2rem; }
.expfull h1 { margin: 0 0 .3rem; font-size: 1.8rem; line-height: 1.15; text-wrap: balance; }
.expfull__meta { margin: 0 0 1.1rem; color: var(--text-muted); font-size: .92rem; }
.expfull__body { white-space: pre-wrap; line-height: 1.65; }

/* Choosing a sitting. Whole rows are the target, not just the radio — this is
   read on a phone with a thumb. */
.slotlist { display: grid; gap: .5rem; margin-top: .5rem; }
.slot { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .7rem;
        align-items: start; padding: .7rem .85rem; cursor: pointer;
        border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fff; }
.slot:hover { border-color: #bdb3a6; }
.slot input { accent-color: var(--orange); margin: .2rem 0 0; }
.slot input:checked ~ .slot__body .slot__when { color: var(--orange-dark); }
.slot:has(input:checked) { border-color: var(--orange); box-shadow: inset 0 0 0 1px var(--orange); }
.slot__body { display: grid; gap: .15rem; }
.slot__when { font-weight: 600; font-size: .95rem; }
.slot__where { font-size: .85rem; color: var(--text-muted); }
.bookform legend { font-size: .82rem; font-weight: 600; padding: 0; }
.bookform fieldset { border: 0; padding: 0; margin: 0; }

/* The reference, which is the actual record — the email may not arrive. */
.refcard__code { display: grid; gap: .2rem; }
.refcard__code span { font-size: .8rem; color: var(--text-muted);
                      text-transform: uppercase; letter-spacing: .06em; }
.refcard__code strong { font-size: 1.9rem; letter-spacing: .12em;
                        font-variant-numeric: tabular-nums; }

/* Nowhere near the screen, but still fillable by a script. Not display:none —
   some bots skip those. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.allergylist { margin: 0; padding-left: 1.1rem; font-size: .92rem; line-height: 1.7; }

@media (max-width: 34rem) {
  .pub__hero h1, .expfull h1 { font-size: 1.5rem; }
  .expcard__img { height: 150px; }
}
