/* ─────────────────────────────────────────────────────────────────────────
   app.css — the screens the design system does not already cover.

   noti.css holds the product's look. This holds the gate (sign in, onboarding)
   and the handful of app-only pieces: toasts, empty rows, form fields. If a
   rule here would be useful on any screen, it belongs in noti.css instead.
   ───────────────────────────────────────────────────────────────────────── */

/* ── the gate: sign in, sign up, onboarding ─────────────────────────────── */
.gate{min-height:100vh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;padding:28px 18px;gap:20px}
.gate-card{background:var(--white);border-radius:var(--r);padding:38px 34px;width:100%;
  max-width:430px}
.gate.wide .gate-card{max-width:660px}
.gate-logo{justify-content:center;padding-bottom:22px}
.gate-card .logo b{color:var(--ink)}
.gate-card h1{font-size:26px;font-weight:800;letter-spacing:-.03em;line-height:1.15}
.gate-sub{font-size:15px;color:var(--grey);font-weight:500;margin-top:8px;line-height:1.55}
.gate-sub b{color:var(--ink);font-weight:700}
.gate-form{display:flex;flex-direction:column;gap:13px;margin-top:24px}
.gate-alt{font-size:14px;color:var(--grey);font-weight:500;margin-top:20px;text-align:center}
.gate-foot{font-size:13.5px;color:var(--grey);font-weight:500}
.gate-foot b{color:var(--ink);font-weight:700}

.fld{display:flex;flex-direction:column;gap:6px}
.fld span{font-size:13px;font-weight:700;color:var(--mid)}
.fld input{border:1.5px solid var(--line);background:var(--cream-2);border-radius:14px;
  padding:14px 16px;font-size:15px;font-family:inherit;color:var(--ink);outline:none;
  font-weight:500;width:100%}
/* A textarea in a .fld was only ever styled inside .panel, so the same field
   on the booking page rendered as the browser's default: monospace, square,
   and obviously not part of the form above it. */
.fld textarea{border:1.5px solid var(--line);background:var(--cream-2);
  border-radius:14px;padding:13px 15px;font:inherit;font-size:15px;
  font-weight:600;color:var(--ink);outline:none;width:100%;resize:vertical;
  line-height:1.5}
.fld textarea:focus{border-color:var(--orange);background:var(--white)}
.fld input::placeholder,.fld textarea::placeholder{color:var(--faint);font-weight:500}
.fld input:focus{border-color:var(--orange);background:var(--white)}

.linkish{font-size:14px;font-weight:700;color:var(--orange);text-decoration:underline;
  text-underline-offset:2px}

/* the gate's buttons are full width; the app's are not, so .big is redefined
   rather than shared */
.gate .big,.onb .big{width:100%;margin:0;padding:15px;border-radius:99px;background:var(--orange);
  color:#fff;font-size:15.5px;font-weight:800;display:flex;align-items:center;
  justify-content:center;gap:8px;letter-spacing:-.01em;border:0}
.gate .big:hover,.onb .big:hover{background:var(--orange-d)}
.gate .big:disabled{opacity:.55;cursor:default}
.gate .big.ghost,.onb .big.ghost{background:var(--cream);color:var(--ink)}
.gate .big.ghost:hover,.onb .big.ghost:hover{background:var(--line)}

/* ── onboarding ─────────────────────────────────────────────────────────── */
.onb-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}
.onb-top .logo{padding:0}
.onb-top .logo b{color:var(--ink);font-size:22px}
.steps{display:flex;gap:6px}
.steps .dot{width:7px;height:7px;border-radius:50%;background:var(--line)}
.steps .dot.past{background:var(--faint)}
.steps .dot.on{background:var(--orange);width:22px;border-radius:99px}

.onb-nav{display:flex;gap:10px;margin-top:24px}
.onb-nav .big{flex:1}

.typegrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:9px;
  margin-top:22px}
.type{text-align:left;padding:15px 16px;border-radius:var(--r2);background:var(--cream-2);
  border:2px solid transparent;transition:.14s}
.type:hover{border-color:var(--line)}
.type.on{background:var(--orange);border-color:var(--orange)}
.type b{display:block;font-size:15px;font-weight:700;letter-spacing:-.015em}
.type span{display:block;font-size:12.5px;color:var(--grey);margin-top:3px;font-weight:500}
.type.on b,.type.on span{color:#fff}
.type.on span{opacity:.8}

.qlist{display:flex;flex-direction:column;gap:7px;margin-top:22px;max-height:46vh;
  overflow-y:auto;padding-right:4px}
.qlist::-webkit-scrollbar{width:8px}
.qlist::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
.q{display:flex;align-items:center;gap:13px;padding:13px 15px;border-radius:var(--r2);
  background:var(--cream-2);text-align:left;border:2px solid transparent;transition:.14s}
.q:hover{border-color:var(--line)}
.q.on{background:#FFF6F1;border-color:var(--orange)}
.q .box{width:26px;height:26px;border-radius:9px;background:var(--white);
  border:1.5px solid var(--line);display:flex;align-items:center;justify-content:center;flex:none}
.q .box svg{width:15px;height:15px;stroke-width:3;color:transparent}
.q.on .box{background:var(--orange);border-color:var(--orange)}
.q.on .box svg{color:#fff}
.q .t{flex:1;min-width:0}
.q .t b{display:block;font-size:14.5px;font-weight:700;letter-spacing:-.01em}
.q .t span{display:block;font-size:12.5px;color:var(--grey);margin-top:2px;font-weight:500}

/* ── the preview step ───────────────────────────────────────────────────── */
.pv{margin-top:22px;border-radius:var(--r2);background:var(--cream-2);overflow:hidden}
.pv-row{display:flex;justify-content:space-between;gap:14px;padding:13px 16px;
  border-bottom:1px solid var(--line)}
.pv-row:last-child{border-bottom:0}
.pv-k{font-size:13.5px;color:var(--grey);font-weight:600}
.pv-v{font-size:14px;font-weight:700;text-align:right}
.pv-lab{font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);margin:22px 0 10px}
.pv-note{font-size:12.5px;color:var(--faint);font-weight:500;margin-top:9px}

.modgrid{display:flex;flex-wrap:wrap;gap:7px}
.mod{display:inline-flex;align-items:center;gap:7px;background:var(--ink);color:#fff;
  border-radius:99px;padding:8px 14px;font-size:13px;font-weight:700}
.mod svg{width:15px;height:15px}

.rulelist{display:flex;flex-direction:column;gap:6px}
.rule{display:flex;align-items:center;gap:10px;background:var(--mint);color:var(--mint-d);
  border-radius:var(--r3);padding:11px 14px;font-size:13.5px;font-weight:600}
.rule svg{width:15px;height:15px;stroke-width:3;flex:none}

/* ── app-only bits ──────────────────────────────────────────────────────── */
.emptyrow{padding:26px 16px;text-align:center;font-size:13.5px;color:var(--faint);
  font-weight:500;line-height:1.6}

.hello .r .chip{border:0;cursor:pointer}
.hello .r .chip svg{width:15px;height:15px;color:inherit}

.toast{position:fixed;left:50%;bottom:26px;transform:translate(-50%,14px);background:var(--ink);
  color:#fff;padding:13px 20px;border-radius:99px;font-size:14px;font-weight:600;z-index:200;
  opacity:0;transition:.22s;box-shadow:0 14px 34px -10px rgba(0,0,0,.4);max-width:90vw}
.toast.in{opacity:1;transform:translate(-50%,0)}
.toast.warn{background:var(--peach-d)}

@media (max-width:640px){
  .gate-card{padding:28px 22px}
  .typegrid{grid-template-columns:1fr}
}

/* ── the slide-over ─────────────────────────────────────────────────────── */
/* One component for every create and edit. Right on a desktop, bottom on a
   phone — the same panel behaving sensibly, not two components. */
.panel-wrap{position:fixed;inset:0;z-index:150;display:flex;justify-content:flex-end}
.panel-bg{position:absolute;inset:0;background:rgba(26,22,19,.42);opacity:0;transition:.22s;
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.panel-wrap.in .panel-bg{opacity:1}
.panel{position:relative;width:min(460px,100%);background:var(--cream);height:100%;
  display:flex;flex-direction:column;transform:translateX(24px);opacity:0;transition:.24s
  cubic-bezier(.22,1,.36,1);box-shadow:-18px 0 50px -20px rgba(26,22,19,.4)}
.panel-wrap.in .panel{transform:none;opacity:1}

.panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;
  padding:26px 26px 18px}
.panel-head h2{font-size:23px;font-weight:800;letter-spacing:-.03em;line-height:1.15}
.panel-head p{font-size:14px;color:var(--grey);font-weight:500;margin-top:6px;line-height:1.5}
.panel-x{width:36px;height:36px;border-radius:50%;background:var(--white);display:flex;
  align-items:center;justify-content:center;flex:none;color:var(--mid)}
.panel-x:hover{background:var(--ink);color:#fff}
.panel-x svg{width:17px;height:17px;transform:rotate(45deg)}

.panel-body{flex:1;overflow-y:auto;padding:4px 26px 26px;display:flex;flex-direction:column;gap:15px}
.panel-body::-webkit-scrollbar{width:8px}
.panel-body::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}

.panel-foot{display:flex;gap:10px;padding:18px 26px calc(22px + env(safe-area-inset-bottom));
  border-top:1px solid var(--line);background:var(--cream)}
.panel-foot .big{flex:1;width:auto;margin:0;padding:15px;border-radius:99px;background:var(--orange);
  color:#fff;font-size:15px;font-weight:800;border:0;display:flex;align-items:center;
  justify-content:center}
.panel-foot .big:hover{background:var(--orange-d)}
.panel-foot .big:disabled{opacity:.55;cursor:default}
.panel-foot .big.ghost{background:var(--white);color:var(--ink);flex:0 0 auto;padding:15px 22px}
.panel-foot .big.ghost:hover{background:var(--line)}

.panel .fld span i{font-style:normal;color:var(--faint);font-weight:500;font-size:12px}
.panel .fld textarea,.panel .fld select{border:1.5px solid var(--line);background:var(--white);
  border-radius:14px;padding:14px 16px;font-size:15px;font-family:inherit;color:var(--ink);
  outline:none;font-weight:500;width:100%;resize:vertical}
.panel .fld input{background:var(--white)}
.panel .fld textarea:focus,.panel .fld select:focus{border-color:var(--orange)}
.panel .fld.bad input,.panel .fld.bad textarea,.panel .fld.bad select{border-color:var(--peach-d)}
.panel .hint{font-style:normal;font-size:12.5px;color:var(--faint);font-weight:500}

.money-in{position:relative;display:flex;align-items:center}
.money-in span{position:absolute;left:16px;font-size:15px;font-weight:700;color:var(--grey);
  pointer-events:none}
.money-in input{padding-left:44px !important}

@media (max-width:640px){
  .panel-wrap{align-items:flex-end}
  .panel{width:100%;height:auto;max-height:92vh;border-radius:26px 26px 0 0;
    transform:translateY(24px)}
  .panel-head{padding:22px 20px 14px}
  .panel-body{padding:4px 20px 20px}
  .panel-foot{padding:16px 20px calc(20px + env(safe-area-inset-bottom))}
}

/* ── the till ───────────────────────────────────────────────────────────── */
/* Products to tap on the left, the basket beside them. On a phone the basket
   drops underneath, which is the same screen with less room rather than a
   different one. */
.tillwrap{display:grid;grid-template-columns:1fr 340px;gap:14px;align-items:start}
.tillgrid{min-height:220px}

.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:9px;
  padding:0 14px 16px}
.ptile{text-align:left;padding:15px 16px;border-radius:var(--r2);background:var(--cream-2);
  border:2px solid transparent;transition:.12s}
.ptile:hover{border-color:var(--orange);background:#FFF6F1}
.ptile:active{transform:scale(.985)}
.ptile b{display:block;font-size:14.5px;font-weight:700;line-height:1.25;letter-spacing:-.012em}
/* A tile with a photo on it. Wide, not square — a bottle cropped to a square
   loses its label, and the label is the thing being looked for. */
.ptile .ppic{display:block;aspect-ratio:16/10;border-radius:9px;overflow:hidden;
  background:var(--line-2);margin:-4px 0 10px}
.ptile .ppic img{width:100%;height:100%;object-fit:cover;display:block}
.ptile.out .ppic{opacity:.45}
.ptile .pr{display:block;font-size:19px;font-weight:800;margin-top:9px;letter-spacing:-.03em}
.ptile .st{display:block;font-size:11.5px;color:var(--faint);font-weight:600;margin-top:3px;
  min-height:14px}
.ptile.low{background:var(--butter)}
.ptile.low .st{color:var(--butter-d)}
.ptile.out{opacity:.45;cursor:not-allowed}
.ptile.out:hover{border-color:transparent;background:var(--cream-2)}

.cart{position:sticky;top:14px;display:flex;flex-direction:column}
.cartlines{padding:0 14px;display:flex;flex-direction:column;gap:6px;max-height:44vh;
  overflow-y:auto}
.cartlines::-webkit-scrollbar{width:7px}
.cartlines::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
.cline{display:flex;align-items:center;gap:11px;padding:11px 13px;border-radius:var(--r3);
  background:var(--cream-2)}
.cline .bd{flex:1;min-width:0}
.cline .bd b{display:block;font-size:13.5px;font-weight:700;line-height:1.25}
.cline .bd span{display:block;font-size:11.5px;color:var(--faint);font-weight:600;margin-top:2px}
.cline .qty{display:flex;align-items:center;gap:2px;flex:none;background:var(--white);
  border-radius:99px;padding:2px}
.cline .qty button{width:26px;height:26px;border-radius:50%;font-size:15px;font-weight:800;
  color:var(--mid);display:flex;align-items:center;justify-content:center;line-height:1}
.cline .qty button:hover{background:var(--orange);color:#fff}
.cline .qty span{min-width:20px;text-align:center;font-size:13.5px;font-weight:700}
.cline .amt{font-size:14px;font-weight:700;flex:none;min-width:62px;text-align:right}

.carttotal{display:flex;justify-content:space-between;align-items:baseline;
  padding:16px 20px 14px;margin-top:12px;border-top:1.5px solid var(--line)}
.carttotal span{font-size:14px;font-weight:700;color:var(--grey)}
.carttotal b{font-size:27px;font-weight:800;letter-spacing:-.035em}

.paybtn{margin:0 16px 18px;padding:16px;border-radius:99px;background:var(--orange);color:#fff;
  font-size:15.5px;font-weight:800;display:flex;align-items:center;justify-content:center;gap:9px;
  border:0}
.paybtn:hover{background:var(--orange-d)}
.paybtn:disabled{background:var(--line);color:var(--faint);cursor:default}
.paybtn svg{width:18px;height:18px}

@media (max-width:1000px){
  .tillwrap{grid-template-columns:1fr}
  .cart{position:static}
}

.cartgst{padding:0 20px 12px;margin-top:-8px;font-size:12.5px;color:var(--grey);
  font-weight:600}
.cartgst b{color:var(--ink)}

/* ── the extra pieces the new screens need ──────────────────────────────── */
.card.stacked{margin-bottom:14px}
.cardnote{padding:0 22px 18px;font-size:12.5px;color:var(--faint);font-weight:500;
  line-height:1.6}
.cardnote b{color:var(--mid)}
.cardnote.standalone{background:var(--white);border-radius:var(--r);padding:18px 22px;
  margin-top:14px}
.ch .all{font-size:12.5px;font-weight:700;color:var(--orange);display:flex;
  align-items:center;gap:4px;background:none;border:0}
.ch .all svg{width:14px;height:14px}

.srow .av{width:34px;height:34px;font-size:12px;flex:none;background:var(--lav);
  color:var(--lav-d)}
.srow .cv{width:16px;height:16px;color:var(--faint);flex:none;display:flex}
.srow .cv svg{width:16px;height:16px}
.srow.warn{background:#FDF1EC}
.srow.warn:before{background:var(--peach-d)}
.srow[data-open],.srow[data-cust],.srow[data-work]{cursor:pointer}

/* history inside a panel: how a number got to be that number */
.hist{margin-top:20px;background:var(--white);border-radius:var(--r2);padding:4px 0 6px}
.hist-lab{font-size:11.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);padding:13px 16px 8px}
.hist-row{display:flex;align-items:baseline;gap:12px;padding:8px 16px;font-size:13px}
.hist-row .d{color:var(--faint);font-weight:600;font-size:11.5px;min-width:52px;flex:none}
.hist-row .w{flex:1;min-width:0;color:var(--mid);font-weight:500}
.hist-row .w b{color:var(--ink);font-weight:700}
.hist-row .q{font-weight:700;flex:none}
.hist-row .q.neg{color:var(--peach-d)}
.hist-row .q.pos{color:var(--mint-d)}
.hist-row.total{border-top:1px solid var(--line);margin-top:4px;padding-top:11px}

.minifigs{display:flex;gap:8px;margin-top:18px}
.minifigs > div{flex:1;background:var(--white);border-radius:var(--r2);padding:13px 14px}
.minifigs span{display:block;font-size:11.5px;color:var(--grey);font-weight:600}
.minifigs b{display:block;font-size:18px;font-weight:800;letter-spacing:-.025em;margin-top:5px}

/* ── variants, categories, modifiers ─────────────────────────────────────── */

/* A product that is sold several ways: a header row, then its variants
   indented under it. The indent is the whole explanation. */
.srow.head{background:var(--cream-2);margin-top:6px}
.srow.head .bd b{font-size:14.5px}
.srow.sub{margin-left:20px;padding-left:12px}
.srow.sub:before{left:-20px;background:var(--line)}
.srow.sub .bd b{font-size:13.5px;font-weight:700;color:var(--mid)}

/* Category filter above the till grid. */
.cats{display:flex;gap:7px;flex-wrap:wrap;padding:0 20px 14px}
.cat{padding:7px 15px;border-radius:99px;background:var(--cream-2);font-size:12.5px;
  font-weight:700;color:var(--mid);border:1.5px solid transparent}
.cat:hover{border-color:var(--line)}
.cat.on{background:var(--ink);color:#fff;border-color:var(--ink)}

/* The scanner box. A scanner is a keyboard, so this is just an input. */
.scan{position:relative;display:flex;align-items:center;margin-left:auto}
.scan svg{position:absolute;left:13px;width:15px;height:15px;color:var(--faint);
  pointer-events:none}
.scan input{width:186px;border:1.5px solid var(--line);background:var(--white);
  border-radius:99px;padding:9px 14px 9px 34px;font-size:12.5px;font-family:inherit;
  font-weight:600;color:var(--ink);outline:none}
.scan input::placeholder{color:var(--faint);font-weight:600}
.scan input:focus{border-color:var(--orange);width:220px}

/* Extras chosen on a basket line. */
.cline .bd .mods{font-size:11px;color:var(--orange);font-weight:700;margin-top:3px}

/* What is left after GST and cost. The number Square charges extra for, on
   the screen where the sale is happening. */
.cartmargin{padding:0 20px 14px;margin-top:-6px;font-size:12.5px;color:var(--mint-d);
  font-weight:700}
.cartmargin b{color:var(--mint-d)}

/* Price, cost, and what is actually kept. */
.marginbox{margin-top:20px;background:var(--mint);border-radius:var(--r2);padding:14px 18px}
.marginbox.bad{background:var(--peach)}
.marginbox div{display:flex;justify-content:space-between;align-items:baseline;
  padding:4px 0;font-size:13px;font-weight:600;color:var(--mint-d)}
.marginbox.bad div{color:var(--peach-d)}
.marginbox .tot{border-top:1.5px solid rgba(31,122,76,.22);margin-top:5px;padding-top:9px}
.marginbox.bad .tot{border-top-color:rgba(176,62,20,.22)}
.marginbox .tot b{font-size:19px;font-weight:800;letter-spacing:-.03em}
.marginbox .tot i{font-style:normal;font-size:13px;font-weight:700;opacity:.72}

/* Checkbox rows inside a panel, for picking which extras a product offers. */
.hist-row.pick{cursor:pointer;gap:10px}
.hist-row.pick:hover{background:var(--cream)}
.hist-row.pick input{width:16px;height:16px;accent-color:var(--orange);flex:none}
.hist-row .w{flex:1;min-width:0}
.hist .linkish{font-size:12.5px;margin:6px 16px 4px;display:inline-block}
.linkish.danger{color:var(--peach-d)}

/* Said once, on the screen where it can be acted on, and only while it is
   still true. */
.nudge{margin-bottom:16px;background:var(--butter);display:flex;gap:14px;
  align-items:flex-start;padding:18px 20px}
.nudge-b b{display:block;font-size:14.5px;font-weight:800;color:var(--butter-d);
  letter-spacing:-.012em}
.nudge-b span{display:block;font-size:13px;color:var(--butter-d);font-weight:600;
  margin-top:4px;max-width:70ch;line-height:1.5}

@media (max-width:900px){
  .scan input{width:130px}
  .scan input:focus{width:150px}
  .srow.sub{margin-left:12px}
}

/* ── needs attention ─────────────────────────────────────────────────────── */

/* A row that needs somebody today reads differently from one that can wait.
   The edge does it, not colour alone — the tone chip is already carrying a
   meaning and two signals in one place is one too many. */
.trow.urgent{background:var(--cream-2);position:relative}
.trow.urgent:before{content:'';position:absolute;left:0;top:9px;bottom:9px;width:3px;
  border-radius:3px;background:var(--orange)}
.trow .amt{font-size:13.5px;font-weight:700;flex:none;margin-right:2px}
.trow .bd span{line-height:1.35}

.morerow{padding:10px 16px 4px;font-size:12.5px;font-weight:600;color:var(--faint)}

/* Nothing wrong is a real answer and gets a real panel. */
.allclear{padding:26px 20px;text-align:center}
.allclear svg{width:26px;height:26px;color:var(--mint-d);stroke-width:2.6;margin-bottom:8px}
.allclear b{display:block;font-size:15px;font-weight:800;letter-spacing:-.015em}
.allclear span{display:block;font-size:13px;color:var(--grey);font-weight:600;margin-top:4px;
  max-width:34ch;margin-left:auto;margin-right:auto;line-height:1.45}

/* ── what Noti handled ───────────────────────────────────────────────────── */
/* A skip is not a failure and must not read as one. Acted is green, skipped is
   a neutral blue, asked is amber, failed is the only one that looks like a
   problem — because it is the only one that is. */
.drow .tk.t-mint{color:var(--mint-d)}
.drow .tk.t-sky{color:var(--sky-d)}
.drow .tk.t-butter{color:var(--butter-d)}
.drow .tk.t-peach{color:var(--peach-d)}
.drow.skipped .bd b{color:var(--mid);font-weight:600}
.drow.failed{background:#FDF3EF;border-radius:var(--r3)}

/* A line of explanation under a settings card, where the reason for a setting
   matters as much as the value. */
.note{padding:2px 22px 18px;font-size:12.5px;color:var(--grey);font-weight:600;
  line-height:1.5;max-width:62ch}
.sched em{font-style:normal;color:var(--peach-d);font-weight:700}

/* Report range picker — the same chips as the till's categories. */
.ranges{display:flex;gap:7px;flex-wrap:wrap}
.cardnote{padding:2px 22px 18px;font-size:12.5px;color:var(--grey);font-weight:600;
  line-height:1.5;max-width:64ch}

/* Arriving from an invite. Says what this is before anybody types a password. */
.invite-chip{display:inline-block;background:var(--lav);color:var(--lav-d);
  font-size:11.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  padding:6px 12px;border-radius:99px;margin-bottom:14px}

/* ── pairing a device ────────────────────────────────────────────────────── */
/* Read across a room, or through somebody's phone camera. Big on purpose. */
.paircode{text-align:center;padding:8px 0 4px}
.paircode .code{font-size:40px;font-weight:600;letter-spacing:.16em;
  background:var(--cream-2);border-radius:var(--r2);padding:18px 10px}
.paircode .dies{font-size:12.5px;font-weight:600;color:var(--grey);margin-top:10px}
.paircode .qr{margin:18px auto 6px;width:180px;height:180px;background:#fff;
  border-radius:var(--r2);padding:10px;box-sizing:content-box}
.paircode .qr svg{width:100%;height:100%;display:block}
/* The bare svg rule at the top of this file is for the icon set — hairline,
   round, no fill. A QR is the opposite: a grid of exact one-unit squares. Left
   alone it gets drawn with a 1.9-unit rounded stroke on a 31-unit grid, which
   smears the modules into each other and no scanner can read it. */
.paircode .qr svg path{stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter}
.paircode .qr svg path[fill]{fill:#fff;stroke:none}
.paircode .qr svg path[stroke]{stroke:#000}
.paircode .orlink{font-size:12px;font-weight:600;color:var(--faint);line-height:1.6}
.paircode .small{font-size:11px;word-break:break-all;color:var(--grey)}

/* ── the first screen, and the lock screen ────────────────────────────────
   Two doors, a code box and a PIN pad. All of it is touched with a thumb on a
   counter more often than clicked with a mouse, so the targets are large and
   the type is big enough to read at arm's length. */

.doors{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:26px}
.door{display:flex;flex-direction:column;align-items:flex-start;gap:7px;
  text-align:left;background:var(--cream);border:1.5px solid transparent;
  border-radius:var(--r2);padding:22px 20px 18px;cursor:pointer;
  transition:border-color .12s,background .12s}
.door:hover{background:var(--white);border-color:var(--ink)}
.door .di{display:grid;place-items:center;width:38px;height:38px;border-radius:12px;
  background:var(--white);color:var(--ink);margin-bottom:4px}
.door:hover .di{background:var(--orange);color:#fff}
.door .di svg{width:19px;height:19px}
.door b{font-size:16.5px;font-weight:800;letter-spacing:-.02em}
.door>span{font-size:13.5px;font-weight:500;color:var(--grey);line-height:1.5}
.door em{font-style:normal;font-size:13.5px;font-weight:800;color:var(--orange-d);
  margin-top:6px}

.codein{text-align:center;font-size:30px;font-weight:700;letter-spacing:.28em;
  text-transform:uppercase;padding:16px 10px 16px 20px}

.lockgate .gate-card{padding-top:26px}
.lockhead{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding-bottom:20px}
.lockhead .gate-logo{padding:0;justify-content:flex-start}
.lockwhere{text-align:right;line-height:1.35}
.lockwhere b{display:block;font-size:13.5px;font-weight:800}
.lockwhere span{font-size:12.5px;font-weight:600;color:var(--faint)}
.backish{display:inline-flex;align-items:center;gap:5px;font-size:13.5px;
  font-weight:700;color:var(--grey);background:none;cursor:pointer}
.backish:hover{color:var(--ink)}
.backish svg{width:15px;height:15px}

/* Scoped to the lock screen on purpose. noti.css already owns bare .person for
   the calendar's staff columns, and an unscoped rule here silently repainted
   every column on the calendar cream and stacked it — which is exactly the
   class of bug .col and .rule caused on the same screen. A name that already
   exists in the design system gets a parent, not a redefinition. */
.people{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));
  gap:12px;margin-top:22px}
.lockgate .person{display:flex;flex-direction:column;align-items:center;gap:8px;
  background:var(--cream);border:1.5px solid transparent;border-radius:var(--r2);
  padding:20px 12px;cursor:pointer;transition:border-color .12s,background .12s;
  min-width:0;text-align:center}
.lockgate .person:hover{background:var(--white);border-color:var(--ink)}
.pav{display:grid;place-items:center;width:52px;height:52px;border-radius:50%;
  background:var(--orange);color:#fff;font-size:21px;font-weight:800}
.lockgate .person b{font-size:15px;font-weight:800;letter-spacing:-.02em}
.lockgate .person .prole{font-size:12px;font-weight:600;color:var(--faint);
  text-transform:capitalize}
.lockgate .person[data-nopin] .pav{background:var(--line);color:var(--faint)}

.dots{display:flex;justify-content:center;gap:11px;margin:26px 0 22px}
.dots i{width:12px;height:12px;border-radius:50%;background:var(--line)}
/* The first four are outlined, so eight circles do not read as "type eight". */
.dots i.need{box-shadow:inset 0 0 0 1.5px var(--faint);background:transparent}
.dots i.on{background:var(--ink);box-shadow:none}

.pad{display:grid;grid-template-columns:repeat(3,1fr);gap:11px;max-width:290px;
  margin:0 auto}
.key{height:62px;border-radius:16px;background:var(--cream);font-size:24px;
  font-weight:700;cursor:pointer;transition:background .1s;
  -webkit-tap-highlight-color:transparent}
.key:hover{background:var(--line)}
.key:active{background:var(--ink);color:var(--white)}
.key.ghosty{background:transparent;color:var(--grey)}
.key.ghosty:hover{background:var(--cream);color:var(--ink)}
.key.go{background:var(--orange);color:#fff}
.key.go:hover{background:var(--orange-d)}
.key.go.working{opacity:.6}
.key svg{width:21px;height:21px;margin:0 auto}

@media (max-width:560px){
  .doors{grid-template-columns:1fr}
  .door{padding:18px 16px 15px}
}

/* ── categories ───────────────────────────────────────────────────────────
   A category is a coloured button on the till and a heading in the catalogue.
   Both live here so they cannot drift apart. */

.chipn{display:inline-grid;place-items:center;min-width:17px;height:17px;padding:0 5px;
  border-radius:99px;background:var(--line);color:var(--mid);font-size:11px;
  font-weight:800;margin-left:3px}
.chip.dark .chipn{background:rgba(255,255,255,.22);color:#fff}

.cats .cat span{display:inline-block;margin-left:5px;color:var(--faint);font-weight:800}
.cat.on span{color:rgba(255,255,255,.62)}
.cat.c-lav{background:var(--lav);color:var(--lav-d)}
.cat.c-mint{background:var(--mint);color:var(--mint-d)}
.cat.c-sky{background:var(--sky);color:var(--sky-d)}
.cat.c-butter{background:var(--butter);color:var(--butter-d)}
.cat.c-peach{background:var(--peach);color:var(--peach-d)}
.cat.c-lav span,.cat.c-mint span,.cat.c-sky span,
.cat.c-butter span,.cat.c-peach span{color:inherit;opacity:.62}
.cat.on.c-lav,.cat.on.c-mint,.cat.on.c-sky,
.cat.on.c-butter,.cat.on.c-peach{background:var(--ink);color:#fff}

/* A heading inside a card, between groups. Quieter than the card's own title,
   because it is a divider rather than a new subject. */
.grouphead{display:flex;align-items:center;gap:7px;padding:14px 22px 6px;
  font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint)}
.grouphead span{font-size:11px;color:var(--mid);background:var(--cream);
  border-radius:99px;padding:1px 7px;letter-spacing:0}

.catlist{display:flex;flex-direction:column;gap:7px}
.catitem{display:flex;align-items:center;gap:11px;background:var(--cream-2);
  border-radius:var(--r2);padding:11px 13px;cursor:grab}
.catitem.lifting{opacity:.4;cursor:grabbing}
/* Six dots, drawn rather than fetched. A chevron here read as "open me". */
.catitem .grip{flex:none;width:9px;height:14px;
  background-image:radial-gradient(var(--faint) 42%, transparent 45%);
  background-size:4.5px 4.5px;opacity:.75}
.catitem .bd{flex:1;min-width:0;line-height:1.3}
.catitem .bd b{display:block;font-size:14.5px;font-weight:700}
.catitem .bd span{font-size:12px;font-weight:600;color:var(--faint)}
.swatch{width:15px;height:15px;border-radius:5px;flex:none}
.swatch.s-lav{background:var(--lav-d)}
.swatch.s-mint{background:var(--mint-d)}
.swatch.s-sky{background:var(--sky-d)}
.swatch.s-butter{background:var(--butter-d)}
.swatch.s-peach{background:var(--peach-d)}

.mini{padding:5px 9px;border-radius:8px;background:var(--white);font-size:12px;
  font-weight:700;color:var(--mid);cursor:pointer;flex:none}
.mini:hover{background:var(--line);color:var(--ink)}

/* Removing is not saving, so it does not look like the save button. */
.dangerish{width:100%;margin-top:18px;padding:12px;border-radius:99px;
  background:var(--peach);color:var(--peach-d);font-size:14px;font-weight:700;
  cursor:pointer}
.dangerish:hover{background:var(--peach-d);color:#fff}
.fineprint{font-size:12.5px;font-weight:500;color:var(--grey);line-height:1.55;
  margin-top:10px}

/* ── settings ─────────────────────────────────────────────────────────────
   A settings screen grows forever, and eight stacked cards means scrolling to
   find the one thing you came for. A rail down the side turns that into one
   click, and gives anything that is not set somewhere to shout from. */

.setwrap{display:grid;grid-template-columns:214px 1fr;gap:18px;align-items:start}
.setnav{display:flex;flex-direction:column;gap:2px;position:sticky;top:18px}
.si{display:flex;align-items:center;gap:10px;width:100%;padding:10px 13px;
  border-radius:var(--r2);background:none;font-size:14px;font-weight:600;
  color:var(--mid);cursor:pointer;text-align:left}
.si svg{width:16px;height:16px;flex:none;color:var(--faint)}
.si span{flex:1;min-width:0}
.si:hover{background:var(--cream-2);color:var(--ink)}
.si.on{background:var(--white);color:var(--ink);font-weight:700}
.si.on svg{color:var(--orange)}
/* Not a count and not a badge — just "there is something here". */
.needs{width:7px;height:7px;border-radius:50%;background:var(--orange);flex:none}

.setbody{display:flex;flex-direction:column;gap:16px;min-width:0}
.setbody .card{margin:0}

/* A row you can click opens whatever changes it. */
.srow.clicky{cursor:pointer}
.srow.clicky:hover{background:var(--cream)}
.rowchev{color:var(--faint);display:flex;flex:none}
.rowchev svg{width:15px;height:15px}
.srow.clicky:hover .rowchev{color:var(--ink)}
.unset{font-style:italic;color:var(--orange-d);font-weight:700}

@media (max-width:900px){
  .setwrap{grid-template-columns:1fr}
  .setnav{position:static;flex-direction:row;overflow-x:auto;gap:6px;
    padding-bottom:4px;-webkit-overflow-scrolling:touch}
  .si{width:auto;flex:none;padding:9px 14px;border-radius:99px;
    background:var(--cream-2);white-space:nowrap}
  .si span{flex:none}
  .si svg{display:none}
}

/* ── the bar chart ────────────────────────────────────────────────────────
   Divs, not a library. The only things read off a chart this size are which
   bar is tallest and whether the right-hand end is going up. */

.bars{display:flex;align-items:flex-end;gap:4px;height:152px;padding:8px 22px 14px}
.bar{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;
  gap:7px;height:100%}
/* No track behind each bar. Thirty pale rectangles for thirty quiet days read
   as stripes, and the one day something happened disappears into them. A
   baseline and the bars themselves are the whole chart. */
/* .stack, not .col — noti.css already owns .col for the day columns in the
   schedule, and inheriting its 150px minimum and left border turned this chart
   into a faint grid with eleven bars in it. */
.bar .stack{flex:1;width:100%;display:flex;align-items:flex-end;
  border-bottom:1.5px solid var(--line)}
.bar i{display:block;width:100%;min-height:1.5px;background:var(--orange-l);
  border-radius:4px 4px 0 0;transition:height .25s,background .12s}
.bar:hover i{background:var(--orange)}
/* An empty day is a flat mark on the baseline, not a gap: the run of quiet
   days is the thing worth seeing. */
.bar i[style*="height:0%"]{background:var(--line);min-height:2px}
.bar span{font-size:10.5px;font-weight:700;color:var(--faint);white-space:nowrap;
  overflow:hidden;height:12px}
@media (max-width:760px){ .bars{height:120px;padding-inline:14px} }

/* ── the calendar ─────────────────────────────────────────────────────────
   noti.css already owns the calendar vocabulary — .calwrap, .calhead,
   .person, .gutter, .col, .block and the b-* palette, on a 68px hour. This
   file only adds the three things that vocabulary does not have, because Noti
   keeps time in four ways and a design system built around appointments only
   models one of them:

     the week view      seven columns of chips, for a trade whose answer is
                        "Tuesday" rather than "Tuesday at 2:15"
     the all-day band   work that is a day, not a time, sitting above the grid
     off-hours shading  outside trading hours, shaded but never blocked
   ───────────────────────────────────────────────────────────────────────── */

.daynav{display:flex;align-items:center;gap:6px}
.daynav .rnd{width:32px;height:32px}
.daynav .rnd svg{width:15px;height:15px}
.daynav .chip{padding:7px 14px}

/* A column wider than about 280px is wasted: a calendar is read down, not
   across, and a two-hour booking stretched over 800 pixels reads as a banner
   with a word in the corner rather than as an appointment. --cols is set by
   the pane, so three staff fill more of the card than two and twelve staff
   scroll sideways the way they should. */
/* The cap goes on the card, not on the grid inside it. Capping the grid alone
   left a field of empty white to the right of the last column, which reads as
   something that failed to load. */
.card.cal{max-width:calc(62px + var(--cols,6) * 280px + 2px)}

/* Shaded, not blocked. Plenty of work happens outside the hours a shop says it
   keeps, and a calendar's job is to show it rather than argue. */
.col .offhours{position:absolute;left:0;right:0;background:var(--cream);
  opacity:.7;pointer-events:none}
.col .nowline{position:absolute;left:0;right:0;height:2px;background:var(--orange);
  z-index:3;pointer-events:none}
.col .nowline::before{content:"";position:absolute;left:-3px;top:-3px;width:8px;
  height:8px;border-radius:50%;background:var(--orange)}

/* Cancelled is not a colour in the palette, because it is an absence. */
.block.b-gone{background:var(--cream-2);color:var(--faint)}
.block.b-gone b{text-decoration:line-through}
/* A window is not an appointment and should not be drawn as one. */
.block.b-window{background:repeating-linear-gradient(135deg,var(--sky) 0 11px,
  #E9F1FA 11px 22px);color:var(--sky-d)}
.block.tight{padding:4px 10px}
.block.tight span,.block.tight .t{display:none}
.block.tight b{margin-top:0}

/* The week. Seven columns of chips, not seven grids — at this width a week
   grid is unreadable, and it was never the right shape for a trade. */
.week{display:grid;grid-template-columns:repeat(7,1fr);padding:0;overflow:hidden}
.wday{border-left:1px solid var(--line-2);min-height:300px;display:flex;
  flex-direction:column;cursor:pointer}
.wday:first-child{border-left:0}
.wday:hover{background:var(--cream-2)}
.wday.now .wday-h{background:var(--ink);color:#fff}
.wday.now .wday-h i{color:rgba(255,255,255,.7)}
.wday.shut{background:#FCFAF7}
.wday-h{display:flex;align-items:baseline;gap:6px;padding:11px 12px;
  border-bottom:1px solid var(--line-2)}
.wday-h b{font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.05em}
.wday-h span{font-size:15px;font-weight:800}
.wday-h i{margin-left:auto;font-style:normal;font-size:10.5px;font-weight:700;
  color:var(--faint)}
.wday-b{flex:1;padding:8px;display:flex;flex-direction:column;gap:6px}
.wnone{font-size:11px;font-weight:700;color:var(--faint);padding:4px}

/* A chip is a block that is not on a grid. Same palette, so a job is the same
   colour whichever view you are looking at it in. */
.wchip{border-radius:9px;padding:7px 9px;cursor:pointer;line-height:1.32;
  background:var(--cream);color:var(--mid)}
.wchip:hover{filter:brightness(.97)}
.wchip .wt{display:block;font-style:normal;font-size:10.5px;font-weight:700;opacity:.75}
.wchip b{display:block;font-size:12.5px;font-weight:800;letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wchip span{display:block;font-size:11px;font-weight:600;opacity:.78;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wchip.b-lav{background:var(--lav);color:var(--lav-d)}
.wchip.b-sky,.wchip.b-window{background:var(--sky);color:var(--sky-d)}
.wchip.b-mint{background:var(--mint);color:var(--mint-d)}
.wchip.b-butter{background:var(--butter);color:var(--butter-d)}
.wchip.b-peach{background:var(--peach);color:var(--peach-d)}
.wchip.b-gone{background:var(--cream-2);color:var(--faint)}
.wchip.b-gone b{text-decoration:line-through}

/* A landscaper's Tuesday is not nine to five, it is Tuesday. */
.allday{display:flex;align-items:flex-start;gap:14px;padding:12px 16px;
  margin-bottom:12px;max-width:calc(62px + var(--cols,6) * 280px + 2px)}
.allday-l{flex:none;width:62px;font-size:11px;font-weight:800;color:var(--faint);
  text-transform:uppercase;letter-spacing:.05em;padding-top:6px}
.allday-r{flex:1;display:flex;flex-wrap:wrap;gap:7px}
.allday-r .wchip{min-width:150px}

@media (max-width:900px){
  .week{grid-template-columns:1fr}
  .wday{min-height:0;border-left:0;border-top:1px solid var(--line-2)}
}

/* A circle with a face in it. .av already sets the size and the shape wherever
   it is used, so this only has to stop the image escaping it. */
.av.has-img{padding:0;overflow:hidden;background:var(--line)}
.av.has-img img{width:100%;height:100%;object-fit:cover;display:block}

/* The picker: the photo as it will look, and one button. Somebody setting a
   staff photo wants to see the crop, not a filename. */
.avpick{display:flex;align-items:center;gap:16px;padding:4px 0 2px}
.avpick .av{width:74px;height:74px;font-size:23px;flex:none}
.avpick-b{display:flex;flex-direction:column;gap:7px;align-items:flex-start}
.avpick-b .btn{padding:8px 14px}
.avpick-n{font-size:12px;font-weight:600;color:var(--faint);line-height:1.5}

/* A product photo is a thing on a shelf, so it is not a circle. */
.propic{width:100%;aspect-ratio:16/10;border-radius:var(--r2);overflow:hidden;
  background:var(--cream);display:grid;place-items:center;margin-bottom:4px}
.propic img{width:100%;height:100%;object-fit:cover;display:block}
.propic .none{font-size:12.5px;font-weight:700;color:var(--faint)}

/* The countdown on a live offer. Deliberately the only ticking thing in the
   product: it is the one number that is wrong the instant it is drawn, and it
   is what makes somebody believe the slot is really being held. */
.countdown{font-variant-numeric:tabular-nums}
/* .qn, not .tm — noti.css already uses .srow .tm for a 64px time column, and
   redefining it here would have silently narrowed every time in the app. */
.srow .qn{display:grid;place-items:center;width:22px;height:22px;border-radius:7px;
  background:var(--cream);color:var(--faint);font-size:11px;font-weight:800;flex:none}
.btn.wide{width:100%;justify-content:center;padding:12px;margin-bottom:4px}

/* ── the search box, which until now was a picture of a search box ────────
   noti.css positions `.search svg` absolutely for the magnifying glass. The
   results live inside .search too, so their icons have to be pulled back out
   of that rule — the same collision that has bitten this session four times,
   caught this time before it shipped. */
.results svg{position:static;transform:none;width:15px;height:15px;color:inherit}

.search kbd{position:absolute;right:14px;top:50%;transform:translateY(-50%);
  font:inherit;font-size:11px;font-weight:700;color:var(--faint);
  background:var(--cream);border-radius:6px;padding:2px 7px;pointer-events:none}
/* Gone once the box is in use — on focus, and also whenever there is text in
   it, because a hint you have already taken is just clutter over your typing. */
.search input:focus ~ kbd,
.search input:not(:placeholder-shown) ~ kbd{display:none}

.results{position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:40;
  background:var(--white);border-radius:var(--r2);padding:6px;
  box-shadow:0 12px 34px rgba(26,22,19,.14),0 0 0 1px var(--line-2);
  max-height:min(62vh,420px);overflow-y:auto}
.rrow{display:flex;align-items:center;gap:11px;width:100%;padding:9px 10px;
  border-radius:10px;background:none;cursor:pointer;text-align:left}
.rrow:hover,.rrow.on{background:var(--cream)}
.rk{display:grid;place-items:center;width:28px;height:28px;border-radius:9px;flex:none}
.rk-customer{background:var(--lav);color:var(--lav-d)}
.rk-work{background:var(--sky);color:var(--sky-d)}
.rk-product{background:var(--mint);color:var(--mint-d)}
.rb{flex:1;min-width:0;line-height:1.3}
.rb b{display:block;font-size:14px;font-weight:700;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.rb span{display:block;font-size:12px;font-weight:600;color:var(--faint);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rt{font-size:11px;font-weight:700;color:var(--faint);flex:none}
.rnone{padding:16px 12px;font-size:13px;font-weight:600;color:var(--faint);
  text-align:center}

/* ── a document, inside the panel ─────────────────────────────────────────
   All scoped, because .lb and .tot already mean something elsewhere and this
   session has spent enough time on that lesson. */

.lines{display:flex;flex-direction:column;gap:2px;margin-bottom:14px}
.lrow{display:flex;align-items:center;gap:10px;padding:10px 12px;
  background:var(--cream-2);border-radius:var(--r3,10px)}
.lines .lb{flex:1;min-width:0;line-height:1.3}
.lines .lb b{display:block;font-size:13.5px;font-weight:700}
.lines .lb span{font-size:11.5px;font-weight:600;color:var(--faint)}
.lrow .amt{font-size:13.5px;font-weight:700}

.lsum{margin-top:10px;padding:12px 12px 4px;font-size:13px}
.lsum div{display:flex;justify-content:space-between;padding:4px 0}
.lsum span{color:var(--grey);font-weight:600}
.lsum b{font-weight:700}
.lsum .tot{border-top:1.5px solid var(--line);margin-top:5px;padding-top:9px}
.lsum .tot b{font-size:16px;font-weight:800;letter-spacing:-.02em}

.docacts{display:flex;flex-direction:column;gap:8px;margin-top:18px}
.docacts .big{width:100%}
.hist .small{font-size:11px;word-break:break-all}

/* The same question list onboarding uses, asked again from Settings. Reusing
   .q rather than restyling it, so a business that changes how it works sees
   exactly the screen it first answered on. */
.qlist{display:flex;flex-direction:column;gap:8px}
.qlist .q{width:100%;cursor:pointer}

/* The embed snippet, for copying. Wraps rather than scrolls, because somebody
   selecting it by hand should be able to see all of it. */
.snip{display:block;background:var(--white);border:1.5px solid var(--line);
  border-radius:10px;padding:11px 13px;margin:10px 0;font-size:11.5px;
  line-height:1.6;word-break:break-all;color:var(--mid);user-select:all}

/* ── messages ─────────────────────────────────────────────────────────────
   What went out, and what Noti decided not to send. The second half is the
   part nothing else in this market shows, so it gets the same weight rather
   than being tucked into a filter. */
.srow .mch{display:grid;place-items:center;width:28px;height:28px;flex:none;
  border-radius:9px;background:var(--cream);color:var(--faint)}
.srow .mch svg{width:15px;height:15px}
.srow.warn .mch{background:var(--peach);color:var(--peach-d)}

/* Exactly what was sent, character for character. Monospace on purpose: a
   business asked "what did you send me" should be able to read it back without
   wondering whether the screen has reflowed it. */
.msgbody{background:var(--cream-2);border-radius:var(--r2);padding:15px 17px;
  font-size:13px;line-height:1.65;white-space:pre-wrap;word-break:break-word;
  color:var(--ink);font-weight:500;margin-bottom:16px}
