/* =========================================================================
   מערכת נהלי עבודה למכולת — The Docket Book
   Direction contract lives in index.html, first child of <body>.
   Palette, type roles and component grammar taken from the world's quality
   bar board: tabbed coupon heads, hairline-ruled fixed fields, carbon
   numerals struck into those fields, and a red VOID stamp that cancels
   without erasing.
   ========================================================================= */

/* ------------------------------------------------------------------ tokens */
:root {
  /* Five values, no sixth. Every intermediate tone is a rule weight or a
     screen of the same ink, never a new colour. */
  --navy:        #0D1B3D;
  --red:         #D7262D;
  --coupon:      #FFFFFF;
  --stock:       #F2F2F0;
  --carbon:      #4B2E83;

  /* screens of those inks */
  --navy-2:      rgba(13, 27, 61, 0.62);
  --navy-3:      rgba(13, 27, 61, 0.40);
  --navy-4:      rgba(13, 27, 61, 0.18);
  --rule:        rgba(13, 27, 61, 0.22);
  --rule-2:      rgba(13, 27, 61, 0.45);
  --red-wash:    rgba(215, 38, 45, 0.07);
  --carbon-wash: rgba(75, 46, 131, 0.07);
  --copy:        #B9A9DC;   /* the carbon duplicate stub */

  --radius: 2px;

  /* type */
  --font-he:   'Heebo', system-ui, sans-serif;
  --font-num:  'Oxanium', 'Heebo', system-ui, sans-serif;   /* carbon numerals */
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;   /* codes, tab caps */

  --t-xs:   0.6875rem;
  --t-sm:   0.8125rem;
  --t-base: 0.9375rem;
  --t-md:   1.0625rem;
  --t-lg:   1.3125rem;
  --t-xl:   1.75rem;
  --t-2xl:  2.375rem;
  --t-3xl:  3rem;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px; --s8: 40px; --s9: 56px;

  --tap: 54px;               /* one-handed, behind a counter, in a hurry */
  --shell: 1560px;

  /* the security-printed ground */
  --security: radial-gradient(circle at 1px 1px, rgba(13,27,61,0.10) 1px, transparent 1.4px);
  --hatch: repeating-linear-gradient(-45deg, var(--red) 0 3px, transparent 3px 7px);
}

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

html {
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  /* The lit-fluorescent paper look is a decision, not a default. Without this
     a phone in dark mode repaints inputs, scrollbars and pickers against it. */
  color-scheme: light;
  /* A pull past the end of the page must not rubber-band the whole shell. */
  overscroll-behavior-y: none;
}

/* index.html asks for viewport-fit=cover, so the page is drawn under the notch
   and the home bar. Everything that touches an edge has to pay the inset back.
   Physical sides on purpose: the notch does not flip with dir="rtl". */
:root {
  --sa-t: env(safe-area-inset-top, 0px);
  --sa-b: env(safe-area-inset-bottom, 0px);
  --sa-l: env(safe-area-inset-left, 0px);
  --sa-r: env(safe-area-inset-right, 0px);
}

/* One hand, behind a counter, on a phone that may be old. Kills the 300ms
   double-tap wait without disabling pinch zoom. */
button, a, label, select, summary,
.input, .textarea, .fieldrow, .stub, .crew__btn, .keypad__key, [role='button'] {
  touch-action: manipulation;
}

body {
  margin: 0;
  min-height: 100dvh;
  font-family: var(--font-he);
  font-size: var(--t-base);
  line-height: 1.5;
  color: var(--navy);
  background: var(--stock);
  background-image: var(--security);
  background-size: 7px 7px;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Paper fibre. Enough to stop the whites reading as screen white. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 999;
  pointer-events: none; opacity: 0.35; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.09'/%3E%3C/svg%3E");
}

h1, h2, h3, h4 { margin: 0; font-weight: 900; line-height: 1.1; letter-spacing: -0.02em; }
p { margin: 0; }
button, input, textarea, select { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--carbon); outline-offset: 2px; }
::selection { background: var(--carbon); color: var(--coupon); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
[hidden] { display: none !important; }

/* ------------------------------------------------------------- primitives */

/* Tab caps. Latin lands in the mono, Hebrew falls through to Heebo, which
   shreds under wide tracking, so the wide setting is opt-in. */
.label {
  font-family: var(--font-he);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--navy-2);
  line-height: 1.45;
}
.label.mono { font-family: var(--font-mono); letter-spacing: 0.16em; }
.label--ink   { color: var(--navy); }
.label--red   { color: var(--red); }
.label--carbon{ color: var(--carbon); }

.mono   { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.carbon { font-family: var(--font-num); font-weight: 600; color: var(--carbon); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- the coupon */
/* Every panel in this product is a coupon: a tabbed head, ruled fields, and
   an edge that says whether it can still be torn. */
.coupon {
  position: relative;
  background: var(--coupon);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  box-shadow: 0 1px 0 rgba(13, 27, 61, 0.06);
}
.coupon__head {
  display: flex; align-items: stretch; justify-content: space-between;
  flex-wrap: wrap;               /* a head with three tabs must fold, not push the page wide */
  gap: var(--s3);
  border-bottom: 1px solid var(--rule-2);
  background: var(--stock);
}
.coupon__tab {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-inline-start: 1px solid var(--rule);
  font-family: var(--font-he);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: 0;
  text-transform: uppercase; color: var(--navy-2);
  white-space: nowrap;
}
/* Latin and tracking are earned by codes and times, never by Hebrew words. */
.coupon__tab.mono { font-family: var(--font-mono); letter-spacing: 0.12em; }
.coupon__tab:first-child {
  border-inline-start: 0;
  background: var(--navy); color: var(--coupon);
}
.coupon__tab--red:first-child { background: var(--red); }
.coupon__tab--grow { flex: 1; justify-content: flex-end; }
.coupon__body { padding: var(--s4); }
.coupon__body--flush { padding: 0; }
.coupon--live { border-color: var(--navy); box-shadow: 0 0 0 2px var(--navy), 0 2px 0 rgba(13,27,61,0.1); }
.coupon--void { border-color: var(--red); }

/* the torn edge: a hatched strip down the inline-end of a blocked coupon */
.coupon--void::after {
  content: '';
  position: absolute; inset-block: -1px; inset-inline-end: -1px;
  width: 7px;
  background: var(--hatch);
  opacity: 0.5;
}

/* perforation between coupons that tear in sequence */
.perf {
  height: 1px; margin: 0;
  background: repeating-linear-gradient(90deg, var(--rule-2) 0 6px, transparent 6px 12px);
}

/* ------------------------------------------------------- the ruled field */
/* A task is a field on the form. Blank means unsigned. Signing strikes the
   carbon entry into it, and it stays struck. */
.fieldrow {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  align-items: start;
  gap: var(--s4);
  width: 100%;
  min-height: var(--tap);
  padding: var(--s3) var(--s4);
  background: var(--coupon);
  border: 0; border-bottom: 1px solid var(--rule);
  text-align: right;
  cursor: pointer;
  transition: background 140ms ease;
  -webkit-tap-highlight-color: transparent;
}
.fieldrow:last-child { border-bottom: 0; }
.fieldrow:hover:not(:disabled) { background: var(--carbon-wash); }
.fieldrow:disabled { cursor: not-allowed; }

.fieldrow__box {
  position: relative;
  width: 24px; height: 24px; flex: none; margin-top: 3px;
  border: 1.5px solid var(--navy-2);
  background: var(--coupon);
  transition: border-color 160ms ease, background 160ms ease;
}
.fieldrow__box::after {
  content: '';
  position: absolute; inset: -2px;
  background: var(--carbon);
  clip-path: polygon(14% 50%, 38% 74%, 86% 20%, 96% 30%, 38% 92%, 4% 58%);
  opacity: 0; transform: scale(0.4);
  transition: opacity 160ms ease, transform 180ms cubic-bezier(.16,.84,.44,1);
}
.fieldrow__title { display: block; font-weight: 500; line-height: 1.4; }

/* the carbon entry struck into the field once it is signed */
.entry {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s3);
  margin-top: var(--s2);
  padding-top: var(--s2);
  border-top: 1px dotted var(--rule);
  font-family: var(--font-num);
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.04em;
  color: var(--carbon);
  text-transform: uppercase;
}
.entry b { font-family: var(--font-he); font-weight: 700; letter-spacing: 0; text-transform: none; }
.entry__note {
  flex-basis: 100%;
  font-family: var(--font-he); font-size: var(--t-sm); font-weight: 400;
  letter-spacing: 0; text-transform: none; color: var(--navy-2);
}

.fieldrow[data-on='1'] { background: var(--carbon-wash); }
.fieldrow[data-on='1'] .fieldrow__box { border-color: var(--carbon); }
.fieldrow[data-on='1'] .fieldrow__box::after { opacity: 1; transform: none; }
.fieldrow[data-on='1'] .fieldrow__title { color: var(--navy-2); }
.fieldrow[data-flag='burst'] { background: var(--red-wash); }
.fieldrow[data-flag='burst'] .fieldrow__box { border-color: var(--red); }
.fieldrow[data-locked='1'] { opacity: 0.5; }

/* the strike when an entry lands */
@keyframes strike { 0% { transform: scale(1.5); opacity: 0; } 60% { opacity: 1; } 100% { transform: scale(1); } }
.is-striking .fieldrow__box::after { animation: strike 260ms ease-out; }

/* A form this wide with one field per line reads as broken. Two columns at
   desktop width, one on a phone. */
.fields { display: grid; grid-template-columns: 1fr; }
@media (min-width: 720px) {
  .fields { grid-template-columns: 1fr 1fr; }
  .fields .fieldrow:nth-child(odd) { border-inline-end: 1px solid var(--rule); }
}

/* =========================================================== photographic proof
   A photo is a print pasted onto the docket: white mount, hairline rule, one
   hard offset so it sits above the page rather than floating over it. No new
   colour enters here. Carbon means the record accepted it, red means the server
   has a question about it, and the hatch is the same hatch every other hold in
   the book already uses.
   ============================================================================ */

/* the blank frame: unsigned grammar, same as an empty field */
.proof {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s2);
  width: 100%; min-height: 168px;
  padding: var(--s6) var(--s4);
  background: var(--coupon);
  border: 1.5px dashed var(--rule-2);
  border-radius: var(--radius);
  color: var(--navy);
  cursor: pointer;
  text-align: center;
  transition: border-color 140ms ease, background 140ms ease;
}
.proof:hover:not(:disabled) { border-color: var(--carbon); background: var(--carbon-wash); }
.proof:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.proof:disabled { cursor: progress; border-style: solid; border-color: var(--navy-4); }
.proof__mark { width: 30px; height: 30px; color: var(--navy-2); }
.proof__cta { font-weight: 700; font-size: var(--t-md); }
.proof__hint {
  max-width: 34ch;
  font-size: var(--t-xs); line-height: 1.6; color: var(--navy-2);
}

/* the pasted print */
.proof__frame {
  position: relative;
  display: block; flex: none;
  width: 92px; aspect-ratio: 1;
  background: var(--stock);
  border: 1px solid var(--navy);
  box-shadow: 2px 2px 0 var(--navy-4);
  overflow: hidden;
  cursor: zoom-in;
}
.proof__frame--xs { width: 44px; box-shadow: none; }
/* inside a log line the print sits in the text run, not in its own column */
.logline__body .proof__frame { display: inline-block; vertical-align: middle; margin-inline-start: var(--s2); }
.proof__frame--sm { width: 62px; }
.proof__frame--lg {
  width: 100%; aspect-ratio: auto; max-height: 62vh;
  cursor: default; box-shadow: 3px 3px 0 var(--navy-4);
}
.proof__img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0; transition: opacity 200ms ease;
}
.proof__frame--lg .proof__img { height: auto; max-height: 62vh; object-fit: contain; }
.proof__img.is-on { opacity: 1; }

/* the server has a question about this one */
.proof__frame[data-flagged='1'] { border-color: var(--red); box-shadow: 2px 2px 0 var(--red-wash); }
.proof__frame[data-flagged='1']::after {
  content: '';
  position: absolute; inset-block-start: 0; inset-inline-end: 0;
  width: 18px; height: 18px;
  background: var(--hatch);
}
.proof__frame[data-broken='1']::before {
  content: 'אין קובץ';
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-xs); color: var(--navy-2);
}

/* the 64px square the server decoded itself */
/* Shown at its native 64px: the comparison is the whole point, and an upscaled
   or shrunken seal makes the one check a human can perform harder than it is. */
.seal {
  display: inline-block;
  width: 64px; height: 64px;
  border: 1px solid var(--rule-2);
  background: var(--stock);
}
/* Held back until real bytes arrive, exactly like .proof__img. A src-less img
   at full opacity shows its alt text inside the 64px square, which reads as a
   broken seal rather than a seal that has not loaded yet. */
.seal img {
  display: block; width: 100%; height: 100%;
  image-rendering: pixelated;
  opacity: 0; transition: opacity 200ms ease;
}
.seal img.is-on { opacity: 1; }
.seal[data-broken='1'] {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--t-xs); color: var(--navy-2);
}
.seal[data-broken='1']::before { content: 'אין קובץ'; }

/* the contact sheet: the shift's photos in the order they were taken */
.contact {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: var(--s4);
}
.contact--strip { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: var(--s3); }
.contact__i { margin: 0; display: grid; gap: var(--s2); }
.contact__i .proof__frame { width: 100%; }
.contact__c { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s2); }
.contact__t { font-size: var(--t-xs); font-weight: 600; color: var(--carbon); }
.contact__n {
  flex-basis: 100%;
  font-size: var(--t-xs); line-height: 1.4; color: var(--navy-2);
}

/* The trailing column of a field row is the proof slot: a blank frame before,
   the print after. Same square either way, so the line teaches what it wants
   before it is tapped and nothing shifts when it is filled. */
.proof__frame--empty {
  display: flex; align-items: center; justify-content: center;
  background: var(--coupon);
  border: 1.5px dashed var(--rule);
  box-shadow: none;
  cursor: inherit;
}
.proof__ghost { width: 20px; height: 20px; color: var(--navy-3); }
.fieldrow:hover:not(:disabled) .proof__frame--empty { border-color: var(--carbon); }

/* the manager's per-line switch */
.camtoggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none;
  background: var(--coupon);
  border: 1px solid var(--navy-4);
  border-radius: var(--radius);
  color: var(--navy-3);
  cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
}
.camtoggle:hover { border-color: var(--carbon); color: var(--carbon); }
.camtoggle:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.camtoggle[aria-pressed='true'] { background: var(--carbon); border-color: var(--carbon); color: var(--coupon); }
.camtoggle__i { width: 17px; height: 17px; }

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

/* Out of the way until a keyboard asks for it, then a real ticket-stub button. */
.skip {
  position: fixed; z-index: 90;
  inset-inline-start: var(--s4);
  top: calc(-1 * var(--tap) - var(--s4));
  display: grid; place-items: center;
  min-height: var(--tap); padding-inline: var(--s5);
  background: var(--coupon); color: var(--navy);
  border: 1.5px solid var(--navy); border-radius: var(--radius);
  box-shadow: 3px 3px 0 var(--navy-4);
  font-weight: 700; text-decoration: none;
  transition: top 160ms ease;
}
/* Plain :focus, not :focus-visible. Off-screen it cannot be clicked, so Tab is
   the only way in, and a link that stays hidden when focused is not a skip link. */
.skip:focus { top: calc(var(--s4) + var(--sa-t)); outline: 2px solid var(--red); outline-offset: 2px; }
.main:focus { outline: none; }

/* ------------------------------------------------------------- VOID stamp */
.stamp {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 2px var(--s3);
  border: 2px solid var(--red);
  box-shadow: inset 0 0 0 1px var(--coupon), 0 0 0 1px var(--red);
  color: var(--red);
  font-family: var(--font-he);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: 0;
  text-transform: uppercase;
  transform: rotate(-4deg);
  opacity: 0.9;
}
.stamp.mono { font-family: var(--font-mono); letter-spacing: 0.16em; }
.stamp.mono { font-family: var(--font-mono); letter-spacing: 0.16em; }
.stamp--lg { font-size: var(--t-lg); padding: var(--s2) var(--s5); border-width: 3px; }

/* ---------------------------------------------------------- the data row */
.datarow {
  display: flex; align-items: baseline; gap: var(--s3);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--rule);
}
.datarow:last-child { border-bottom: 0; }
.datarow__k { color: var(--navy-2); font-size: var(--t-sm); white-space: nowrap; }
.datarow__fill { flex: 1; border-bottom: 1px dotted var(--rule); transform: translateY(-3px); }
.datarow__v {
  font-family: var(--font-num); font-weight: 600; font-size: var(--t-sm);
  font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--carbon);
}
.datarow__v--alert { color: var(--red); }
.datarow__v--ink   { color: var(--navy); }

/* ------------------------------------------------------------- readouts */
.readout { display: flex; flex-direction: column; gap: 2px; }
.readout__v {
  font-family: var(--font-num); font-weight: 700;
  font-size: var(--t-2xl); line-height: 0.92;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 0.16em;
}
.readout__u {
  font-family: var(--font-mono), var(--font-he);
  font-size: 0.3em; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--navy-2);
}
.readout--sm .readout__v { font-size: var(--t-xl); }
.readout--lg .readout__v { font-size: var(--t-3xl); }
.readout--carbon .readout__v { color: var(--carbon); }
.readout--red .readout__v { color: var(--red); }
.readout--onnavy .readout__v { color: var(--coupon); }
.readout--onnavy .readout__u,
.readout--onnavy .label { color: rgba(255,255,255,0.6); }

/* -------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s3);
  min-height: var(--tap);
  padding: 0 var(--s5);
  background: var(--coupon);
  color: var(--navy);
  border: 1.5px solid var(--navy);
  border-radius: var(--radius);
  font-family: var(--font-he); font-size: var(--t-base); font-weight: 700;
  cursor: pointer;
  transition: background 130ms ease, color 130ms ease, box-shadow 130ms ease, transform 90ms ease;
  -webkit-tap-highlight-color: transparent;
}
.btn:hover:not(:disabled) { background: var(--navy); color: var(--coupon); }
.btn:active:not(:disabled) { transform: translate(1px, 1px); box-shadow: none; }
.btn:disabled {
  background: var(--stock); color: var(--navy-2); border-color: var(--navy-4);
  box-shadow: none; cursor: not-allowed;
}
.btn__arrow { font-family: var(--font-mono); font-size: var(--t-md); line-height: 1; }

/* the printed press: the primary action carries a hard offset shadow */
.btn--primary {
  background: var(--red); color: var(--coupon); border-color: var(--red);
  box-shadow: 3px 3px 0 rgba(13, 27, 61, 0.85);
}
.btn--primary:hover:not(:disabled) { filter: brightness(0.88); }
.btn--primary:disabled { background: var(--stock); color: var(--navy-2); border-color: var(--navy-4); box-shadow: none; }
.btn--carbon { border-color: var(--carbon); color: var(--carbon); }
.btn--carbon:hover:not(:disabled) { background: var(--carbon); color: var(--coupon); }
.btn--danger { border-color: var(--red); color: var(--red); }
.btn--danger:hover:not(:disabled) { background: var(--red); color: var(--coupon); }
.btn--ghost {
  border-color: transparent; background: none; color: var(--navy-2);
  min-height: 44px; padding: 0 var(--s3); font-weight: 700;
  text-decoration: underline; text-decoration-color: var(--navy-4); text-underline-offset: 4px;
}
.btn--ghost:hover:not(:disabled) { background: none; color: var(--red); text-decoration-color: var(--red); }
.btn--block { width: 100%; }
.btn--sm { min-height: 44px; padding: 0 var(--s4); font-size: var(--t-sm); }
.btn--onnavy { background: transparent; color: var(--coupon); border-color: rgba(255,255,255,0.4); }
.btn--onnavy:hover:not(:disabled) { background: var(--coupon); color: var(--navy); border-color: var(--coupon); }
/* ghost stays ghost on navy: without this the white hover fill hides white text */
.btn--onnavy.btn--ghost {
  border-color: transparent; background: none;
  color: rgba(255, 255, 255, 0.78); text-decoration-color: rgba(255, 255, 255, 0.35);
}
.btn--onnavy.btn--ghost:hover:not(:disabled) {
  background: none; color: var(--coupon); text-decoration-color: var(--coupon);
}

/* --------------------------------------------------------------- inputs */
.field { display: flex; flex-direction: column; gap: var(--s2); }
.input, .textarea {
  width: 100%;
  min-height: var(--tap);
  padding: var(--s3) var(--s4);
  background: var(--coupon);
  color: var(--carbon);
  border: 1.5px solid var(--rule-2);
  border-radius: var(--radius);
  font-size: var(--t-base);
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.textarea { min-height: 108px; resize: vertical; line-height: 1.6; color: var(--navy); }
.input::placeholder, .textarea::placeholder { color: var(--navy-2); }
/* The ring replaces the native outline, so it must follow the same rule the
   native one does: keyboard yes, mouse and touch no. */
.input:focus, .textarea:focus { border-color: var(--carbon); outline: none; }
.input:focus-visible, .textarea:focus-visible { box-shadow: 0 0 0 3px var(--carbon-wash); }
.input--num { font-family: var(--font-num); font-weight: 600; font-size: var(--t-lg); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- chips */
.chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 3px var(--s3);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  font-family: var(--font-he);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: 0;
  text-transform: uppercase;
  color: var(--navy-2);
  white-space: nowrap;
}
.chip--live   { border-color: var(--navy); background: var(--navy); color: var(--coupon); }
.chip--ok     { border-color: var(--carbon); color: var(--carbon); }
.chip--warn   { border-color: var(--red); color: var(--red); }
.chip--alert  { border-color: var(--red); background: var(--red); color: var(--coupon); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.dot--pulse { animation: blink 2s steps(1, end) infinite; }
@keyframes blink { 0%, 60% { opacity: 1; } 61%, 100% { opacity: 0.25; } }

/* ----------------------------------------------------------------- shell */
.app { display: none; min-height: 100dvh; flex-direction: column; }
.app.is-on { display: flex; }

.topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: var(--s4);
  padding-block: calc(var(--s3) + var(--sa-t)) var(--s3);
  padding-left: calc(var(--s4) + var(--sa-l));
  padding-right: calc(var(--s4) + var(--sa-r));
  background: var(--navy);
  color: var(--coupon);
  border-bottom: 3px solid var(--red);
}
.topbar__brand { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
.topbar__mark { width: 30px; height: 30px; flex: none; color: var(--coupon); }
.topbar__name { font-size: var(--t-md); font-weight: 900; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar__sub {
  display: block; margin-top: 1px; color: rgba(255,255,255,0.62);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46vw;
}
.topbar__spacer { flex: 1; }
.topbar__readouts { display: flex; gap: var(--s5); flex: none; }
.topbar__readouts .readout__v { font-size: var(--t-lg); color: var(--coupon); }
.topbar__readouts .readout__u,
.topbar__readouts .label { color: rgba(255,255,255,0.55); }

.main {
  flex: 1; width: 100%; max-width: var(--shell); margin: 0 auto;
  padding-block: var(--s5) calc(118px + var(--sa-b));
  padding-left: calc(var(--s4) + var(--sa-l));
  padding-right: calc(var(--s4) + var(--sa-r));
}

.screen { display: none; }
.screen.is-on { display: block; }
@keyframes lay { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.screen__head { display: flex; align-items: flex-start; gap: var(--s4); margin-bottom: var(--s5); flex-wrap: wrap; }
.screen__head > div:first-child { flex: 1; min-width: 240px; }
.screen__title { font-size: var(--t-xl); }
.screen__lead { color: var(--navy-2); font-size: var(--t-sm); margin-top: var(--s2); max-width: 66ch; line-height: 1.6; }

/* --------------------------------------------------------- the book rail */
/* The shift's coupons, in the order they tear. */
.book { padding: 0; }
.stub {
  position: relative;
  display: grid;
  grid-template-columns: 46px 1fr auto;
  align-items: center;
  gap: var(--s3);
  width: 100%;
  padding: var(--s3) var(--s4);
  background: none; border: 0;
  border-bottom: 1px dashed var(--rule);
  text-align: right;
  cursor: pointer;
  transition: background 150ms ease;
}
.stub:last-child { border-bottom: 0; }
.stub:hover:not(:disabled) { background: var(--carbon-wash); }
.stub:disabled { cursor: not-allowed; opacity: 0.45; }

.stub__no {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border: 1.5px solid var(--rule-2);
  font-family: var(--font-num); font-size: var(--t-sm); font-weight: 700;
  color: var(--navy-3);
  font-variant-numeric: tabular-nums;
  transition: border-color 160ms ease, background 160ms ease, color 160ms ease;
}
.stub__title { display: block; font-weight: 700; font-size: var(--t-base); }
.stub__sub { display: block; font-size: var(--t-sm); color: var(--navy-2); margin-top: 1px; }
.stub__v { font-family: var(--font-num); font-weight: 600; font-size: var(--t-sm); color: var(--navy-2); font-variant-numeric: tabular-nums; }

.stub[data-state='done'] .stub__no { background: var(--carbon); border-color: var(--carbon); color: var(--coupon); }
.stub[data-state='done'] .stub__v { color: var(--carbon); }
.stub[data-state='active'] { background: var(--navy); }
.stub[data-state='active'] .stub__title,
.stub[data-state='active'] .stub__v { color: var(--coupon); }
.stub[data-state='active'] .stub__sub { color: rgba(255,255,255,0.6); }
.stub[data-state='active'] .stub__no { background: var(--red); border-color: var(--red); color: var(--coupon); }
.stub[data-state='blocked'] .stub__no { border-color: var(--red); color: var(--red); }
.stub[data-state='blocked'] .stub__v { color: var(--red); }
.stub[data-state='blocked'] { background: var(--red-wash); }

/* -------------------------------------------------------- the hold list */
/* What is stopping the book from closing. Named, never a shrug. */
.hold {
  position: relative;
  display: grid; gap: var(--s2);
  padding: var(--s4);
  padding-inline-start: var(--s6);
  border: 1px solid var(--red);
  background: var(--red-wash);
}
/* held, in the book's own vocabulary: a hatched tear strip, not a slab.
   Suppressed inside an already-torn coupon so one object never wears two. */
.coupon--void .hold { padding-inline-start: var(--s4); }

.hold::before {
  content: '';
  position: absolute; inset-block: 0; inset-inline-start: 0;
  width: 8px;
  background: var(--hatch);
  opacity: 0.55;
}
.hold__head { display: flex; align-items: center; gap: var(--s3); justify-content: space-between; }
.hold__title { font-weight: 900; color: var(--red); }
.hold__list { margin: 0; padding-inline-start: var(--s5); color: var(--navy-2); font-size: var(--t-sm); display: grid; gap: 3px; }

.cleared {
  display: grid; gap: var(--s3); place-items: center; text-align: center;
  padding: var(--s7) var(--s4);
  border: 1px dashed var(--carbon);
  background: var(--carbon-wash);
}

/* ----------------------------------------------------------- the counter */
/* Sign-in: the store's own key pad. */
.gate-in {
  min-height: 100dvh; display: grid; place-items: center;
  padding-block: calc(var(--s5) + var(--sa-t)) calc(var(--s5) + var(--sa-b));
  padding-left: calc(var(--s4) + var(--sa-l));
  padding-right: calc(var(--s4) + var(--sa-r));
}
.gate-in__card { width: min(460px, 100%); display: grid; gap: var(--s4); }
.gate-in__brand {
  display: grid; gap: var(--s2); justify-items: center; text-align: center;
  padding: var(--s6) var(--s4);
  background: var(--navy); color: var(--coupon);
  border-bottom: 3px solid var(--red);
}
.gate-in__brand .label { color: rgba(255,255,255,0.6); }
.gate-in__mark { width: 46px; height: 46px; color: var(--coupon); }

.crew { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2); }
.crew__btn {
  display: grid; gap: 1px; padding: var(--s3) var(--s4);
  min-height: var(--tap);
  background: var(--coupon);
  border: 1.5px solid var(--rule); border-radius: var(--radius);
  text-align: right; cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
}
.crew__btn:hover { border-color: var(--navy); }
.crew__btn[aria-pressed='true'] { border-color: var(--carbon); background: var(--carbon); color: var(--coupon); }
.crew__btn[aria-pressed='true'] .label { color: rgba(255,255,255,0.7); }
.crew__name { font-weight: 700; font-size: var(--t-base); }

.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); direction: ltr; }
.keypad__key {
  min-height: 62px;
  background: var(--coupon);
  border: 1.5px solid var(--rule-2); border-radius: var(--radius);
  font-family: var(--font-num); font-size: var(--t-xl); font-weight: 700;
  color: var(--navy); cursor: pointer;
  transition: border-color 90ms ease, background 90ms ease, color 90ms ease;
}
.keypad__key:hover { border-color: var(--navy); }
.keypad__key:active { background: var(--navy); color: var(--coupon); border-color: var(--navy); }
.keypad__key--fn { font-family: var(--font-he); font-size: var(--t-sm); font-weight: 700; color: var(--navy-2); }

.pinview { display: flex; justify-content: center; gap: var(--s3); direction: ltr; }
.pinview__slot {
  width: 44px; height: 56px;
  display: grid; place-items: center;
  border: 1.5px solid var(--rule-2);
  border-bottom-width: 3px;
  background: var(--coupon);
  font-family: var(--font-num); font-size: var(--t-xl); font-weight: 700; color: var(--carbon);
}
.pinview__slot[data-filled='1'] { border-bottom-color: var(--carbon); }

/* ------------------------------------------------------------- nav bar */
.tabbar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 40;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  background: var(--navy);
  border-top: 3px solid var(--red);
  padding-bottom: var(--sa-b);
  padding-left: var(--sa-l);
  padding-right: var(--sa-r);
}
.tabbar__btn {
  display: grid; justify-items: center; gap: 3px;
  padding: var(--s3) var(--s1) var(--s2);
  background: none; border: 0; cursor: pointer;
  color: rgba(255,255,255,0.6);
  transition: color 140ms ease;
}
.tabbar__btn svg { width: 21px; height: 21px; }
.tabbar__btn span {
  font-family: var(--font-he); font-size: var(--t-xs); font-weight: 700;
}
.tabbar__btn[aria-current='true'] { color: var(--coupon); }
.tabbar__btn[aria-current='true'] svg { color: var(--red); }

/* --------------------------------------------------------------- layout */
.grid { display: grid; gap: var(--s4); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: start; }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); align-items: start; }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); align-items: start; }
/* minmax(0,1fr), not 1fr. A grid item's default min-width is auto, so a single
   panel that cannot shrink below its content widens the track, the track
   overflows the shell, and the whole page scrolls sideways on a phone. */
.stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); align-content: start; }
.stack > * { min-width: 0; }
.stack--sm { gap: var(--s2); }
.row { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.row--end { justify-content: flex-end; }
.row--between { justify-content: space-between; }

/* ------------------------------------------------------------ log lines */
.logline {
  display: grid; grid-template-columns: 78px 1fr auto; gap: var(--s3);
  align-items: baseline;
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--rule);
  font-size: var(--t-sm);
}
.logline:last-child { border-bottom: 0; }
.logline:nth-child(even) { background: rgba(13, 27, 61, 0.025); }
.logline__t { font-family: var(--font-num); font-weight: 600; font-size: var(--t-xs); color: var(--carbon); font-variant-numeric: tabular-nums; }
.logline__who { font-family: var(--font-he); font-size: var(--t-xs); color: var(--navy-2); white-space: nowrap; }
.logline--void .logline__body { color: var(--red); }
.logline--void .logline__label { text-decoration: line-through; text-decoration-color: var(--red); }
.logline--flag { background: var(--red-wash) !important; }

/* ---------------------------------------------------- the carbon copy sheet */
/* The manager's duplicate: hours down the side, sections across, every entry
   struck in its cell. A stack of marks in one cell is the day's cheat, and it
   is a shape before it is a flag. */
.sheet-wrap { width: 100%; overflow-x: auto; overscroll-behavior-x: contain; background: var(--coupon); border: 1px solid var(--rule-2); }
/* The coordinate system is authored LTR (lane 0 is placed on the right by
   arithmetic). Inheriting the document rtl flips every text-anchor. */
.sheet-svg { display: block; direction: ltr; min-width: 640px; width: 100%; height: auto; }
.legend { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.legend__i {
  display: flex; align-items: center; gap: var(--s2);
  font-family: var(--font-he);
  font-size: var(--t-xs); color: var(--navy-2); text-transform: uppercase; letter-spacing: 0;
}

/* meter */
.meter { display: grid; grid-template-columns: 1fr 76px 46px; align-items: center; gap: var(--s3); padding: var(--s2) 0; }
.meter__k { font-size: var(--t-sm); color: var(--navy-2); }
/* both are spans, so they need an explicit box or the fill never lays out */
.meter__track { display: block; height: 9px; background: var(--coupon); border: 1px solid var(--rule); overflow: hidden; }
.meter__fill {
  display: block; height: 100%; width: 100%;
  background: var(--carbon);
  transform-origin: right center;   /* RTL: the bar grows from the start edge */
  transition: transform 360ms cubic-bezier(.16,.84,.44,1);
}
.meter__fill--warn { background: var(--red); }
.meter__v { font-family: var(--font-num); font-weight: 600; font-size: var(--t-xs); text-align: end; color: var(--navy-2); }

/* table */
.tbl { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.tbl th {
  text-align: start; padding: var(--s2) var(--s3);
  background: var(--navy); color: var(--coupon);
  font-family: var(--font-he);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: 0; text-transform: uppercase;
  white-space: nowrap;
}
.tbl td { padding: var(--s3); border-bottom: 1px solid var(--rule); vertical-align: top; }
.tbl tbody tr:nth-child(even) { background: rgba(13, 27, 61, 0.025); }
.tbl__num { font-family: var(--font-num); font-weight: 600; font-variant-numeric: tabular-nums; text-align: end; }
.tbl-wrap { overflow-x: auto; overscroll-behavior-x: contain; }

/* The rule book is one continuous ruled sheet, not eight equal cards. */
.clauses { counter-reset: clause; }
.clause {
  display: grid; grid-template-columns: 42px 1fr; gap: var(--s4);
  padding: var(--s4);
  border-bottom: 1px solid var(--rule);
}
.clause:last-child { border-bottom: 0; }
.clause__no {
  font-family: var(--font-num); font-weight: 700; font-size: var(--t-sm);
  color: var(--carbon); padding-top: 2px;
}
.clause__t { font-weight: 900; font-size: var(--t-md); margin-bottom: var(--s1); }
.clause__b { color: var(--navy-2); line-height: 1.7; max-width: 68ch; }

/* The rule book is one continuous ruled sheet, not eight equal cards. */
.clauses { counter-reset: clause; }
.clause {
  display: grid; grid-template-columns: 42px 1fr; gap: var(--s4);
  padding: var(--s4);
  border-bottom: 1px solid var(--rule);
}
.clause:last-child { border-bottom: 0; }
.clause__no {
  font-family: var(--font-num); font-weight: 700; font-size: var(--t-sm);
  color: var(--carbon); padding-top: 2px;
}
.clause__t { font-weight: 900; font-size: var(--t-md); margin-bottom: var(--s1); }
.clause__b { color: var(--navy-2); line-height: 1.7; max-width: 68ch; }

/* ----------------------------------------------------- empty and loading */
.empty {
  display: grid; gap: var(--s3); place-items: center; text-align: center;
  padding: var(--s9) var(--s4);
  color: var(--navy-2);
}
.empty__mark { width: 44px; height: 44px; opacity: 0.4; }
.empty__title { font-size: var(--t-md); font-weight: 900; color: var(--navy); }
.empty__body { font-size: var(--t-sm); max-width: 46ch; line-height: 1.6; }

.skeleton {
  background: linear-gradient(90deg, rgba(13,27,61,0.05), rgba(13,27,61,0.11), rgba(13,27,61,0.05));
  background-size: 200% 100%;
  animation: sweep 1.3s linear infinite;
}
@keyframes sweep { to { background-position: -200% 0; } }
.skeleton--line { height: 13px; margin: var(--s2) 0; }
.skeleton--row  { height: 60px; margin-bottom: 2px; }

/* -------------------------------------------------------------- feedback */
.toasts {
  position: fixed; z-index: 90; inset-inline: var(--s4);
  bottom: calc(88px + env(safe-area-inset-bottom));
  display: grid; gap: var(--s2); justify-items: center; pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: var(--s3);
  max-width: 560px; padding: var(--s3) var(--s4);
  background: var(--navy); color: var(--coupon);
  border-top: 3px solid var(--red);
  font-size: var(--t-sm);
  box-shadow: 4px 4px 0 rgba(13, 27, 61, 0.2);
  animation: lay 200ms ease both;
}
.toast--ok { border-top-color: var(--copy); }

.notice {
  display: none; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s4);
  background: var(--red); color: var(--coupon);
  font-size: var(--t-sm); font-weight: 700;
}
.notice.is-on { display: flex; }

/* modal */
.sheet {
  position: fixed; inset: 0; z-index: 80;
  display: none; align-items: flex-end; justify-content: center;
  padding-left: var(--sa-l);
  padding-right: var(--sa-r);
  background: rgba(13, 27, 61, 0.55);
}
.sheet.is-on { display: flex; }
.sheet__panel {
  width: min(560px, 100%);
  max-height: 92dvh; overflow-y: auto;
  /* Reaching the end of a long sheet must not start scrolling the book behind it. */
  overscroll-behavior: contain;
  padding: var(--s5) var(--s4) calc(var(--s5) + var(--sa-b));
  background: var(--coupon);
  border-top: 4px solid var(--red);
  animation: up 240ms cubic-bezier(.16,.84,.44,1) both;
}
@keyframes up { from { transform: translateY(22px); opacity: 0; } to { transform: none; opacity: 1; } }

/* --------------------------------------------------------------- desktop */
@media (min-width: 900px) {
  /* An iPad in landscape still has a home bar and a side inset. */
  .main {
    padding-block: var(--s6) calc(var(--s7) + var(--sa-b));
    padding-left: calc(var(--s6) + var(--sa-l));
    padding-right: calc(var(--s6) + var(--sa-r));
  }
  .tabbar { display: none; }
  .layout { display: grid; grid-template-columns: 350px 1fr; gap: var(--s5); align-items: start; }
  .layout__rail { position: sticky; top: 86px; display: grid; gap: var(--s4); }
  .toasts { inset-inline: auto var(--s6); bottom: var(--s6); justify-items: end; }
  .sheet { align-items: center; }
  .crew { grid-template-columns: repeat(3, 1fr); }
  .screen__title { font-size: var(--t-2xl); }
  .topbar { padding: var(--s3) var(--s6); }
  .mgr-layout { display: grid; grid-template-columns: 310px 1fr 330px; gap: var(--s4); align-items: start; }
  .btn--block-mobile { width: auto; }
}
@media (max-width: 899px) {
  /* what to do next comes before the book */
  .layout { display: flex; flex-direction: column; gap: var(--s4); }
  .layout__rail { order: 2; display: grid; gap: var(--s4); }
  .topbar__readouts { gap: var(--s4); }
  .topbar__readouts .readout__v { font-size: var(--t-md); }
  .topbar__hide { display: none; }
  .btn--block-mobile { width: 100%; }
}
@media (max-width: 380px) {
  :root { --t-base: 0.875rem; --s4: 13px; }
  .keypad__key { min-height: 54px; }
  .crew { grid-template-columns: 1fr; }
  .topbar__readouts .readout__u { display: none; }
}

/* ----------------------------------------------------------------- print */
@media print {
  body { background: #fff; background-image: none; }
  body::after, .topbar, .tabbar, .toasts, .notice, .no-print { display: none !important; }
  .screen { display: none !important; }
  .screen.is-on { display: block !important; }
  .coupon { break-inside: avoid; box-shadow: none; }
  .main { padding: 0; max-width: none; }
}

/* ------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
