/* 2 MAN PIZZA
   One type size, one weight, two accents. Everything is Helvetica Neue — no
   webfonts are loaded, so there is nothing to licence and nothing to wait for.

   Every colour in the site is one of the tokens below and nothing reaches for
   a literal, which is the only reason a light mode is a block of overrides
   rather than a rewrite. */

:root{
  --bg:#050505;
  --text:#e6e6e6;
  --dim:#5e5e5e;
  --faint:#3f3f3f;        /* quieter than dim: sold out, gone, unavailable */
  --hair:#1e1e1e;
  --mark:#e03b21;          /* member numbers, and the particle pizza */
  --live:#36c96d;          /* open, and only open */

  --size:13px;
  --tracking:.02em;
  --line:1.75;
  --gap:1.55rem;           /* between groups in the centre stack */
  --pad:clamp(20px,4vw,40px);

  --sans:"Helvetica Neue",Helvetica,Arial,"Liberation Sans",sans-serif;
}

/* ---------- light ----------
   Not white: bone, the colour of the paper the thing would be printed on.
   `--dim` and `--faint` are not the dark values lightened — the eye needs
   more separation from a light ground than a dark one, so both go darker
   than their inverses would suggest. Both accents darken too: #e03b21 on
   bone is legible but thin, and the green far more so. */

@media (prefers-color-scheme:light){
  :root:not([data-theme='dark']){
    --bg:#f2f1ee;
    --text:#0b0b0b;
    --dim:#6f6f6d;
    --faint:#a3a29e;
    --hair:#d9d7d1;
    --mark:#c8300f;
    --live:#1c8f4b;
  }
}

/* An explicit choice wins over the system in both directions. */
:root[data-theme='light']{
  --bg:#f2f1ee;
  --text:#0b0b0b;
  --dim:#6f6f6d;
  --faint:#a3a29e;
  --hair:#d9d7d1;
  --mark:#c8300f;
  --live:#1c8f4b;
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
::selection{background:var(--text);color:var(--bg)}

html,body{height:100%}
body{
  background:var(--bg);color:var(--text);
  font-family:var(--sans);
  font-size:var(--size);font-weight:400;
  letter-spacing:var(--tracking);line-height:var(--line);
  text-transform:uppercase;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
a{color:inherit;text-decoration:none}
button,input{font:inherit;letter-spacing:inherit;color:inherit}
canvas{display:block}

/* ---------- the primitives everything is built from ---------- */

.t{font-size:var(--size);letter-spacing:var(--tracking);line-height:var(--line)}
.dim{color:var(--dim)}
.mark{color:var(--mark)}
.live{color:var(--live)}
.num{font-variant-numeric:tabular-nums}

/* a centred column of lines, evenly spaced */
.stack{
  min-height:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--gap);
  /* extra room at the foot: the footer is fixed, and a long page (the claim
     screen) would otherwise run underneath it */
  padding:calc(var(--pad) * 2.6) var(--pad) calc(var(--pad) * 3.6);
  text-align:center;
}
.group{display:flex;flex-direction:column;align-items:center}
.group--row{flex-direction:row;flex-wrap:wrap;justify-content:center;align-items:baseline;gap:2.2em}

/* the clock, top of the page */
/* The two bars. Same size, same colour, same three-slot grid — a grid and
   not space-between, so the middle slot is centred on the page and not
   wherever the two ends leave it. */
.clock,.foot{
  position:fixed;left:var(--pad);right:var(--pad);z-index:5;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;
  gap:1.5em;font-size:var(--size);line-height:var(--line);
  color:var(--dim);
}
.clock{top:var(--pad);pointer-events:none}
.clock > *:first-child{justify-self:start}
.clock > *:last-child{justify-self:end}
.clock a{pointer-events:auto}

/* The mark sits optically on the cap height rather than the line box, or it
   hangs low against the type beside it. */
.bar__house{
  display:inline-flex;align-items:center;gap:.7em;
  color:var(--dim);transition:color .3s ease;white-space:nowrap;
}
.bar__house:hover{color:var(--text)}
.bar__house .homemark__art{transform:translateY(.5px)}

/* ---------- links ---------- */

.link{position:relative;display:inline-block;transition:color .3s ease}
.link::after{
  content:'';position:absolute;left:0;right:0;bottom:-2px;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:right;
  transition:transform .45s cubic-bezier(.2,.8,.2,1);
}
.link:hover{color:var(--text)}
.link:hover::after{transform:scaleX(1);transform-origin:left}

/* bracketed actions: [ ENTER ] */
.brk{color:var(--dim);transition:transform .45s cubic-bezier(.2,.8,.2,1),color .3s}
.act{background:none;border:0;cursor:pointer;display:inline-flex;gap:.7em;padding:2px 0;text-transform:inherit;font:inherit;letter-spacing:inherit}
.act:hover .brk{color:var(--text)}
.act:hover .brk--l{transform:translateX(-4px)}
.act:hover .brk--r{transform:translateX(4px)}

/* ---------- fields ---------- */

/* No rule under a field. A 290px line under a word is the widest, heaviest
   thing on a page otherwise made of short centred lines, and it was drawing
   the eye to the container rather than to what goes in it.

   What replaces it as the affordance: the placeholder is set in --dim and in
   caps, so it reads as a label you can type over; the first field on every
   form is autofocused, so the caret is already blinking in it on arrival; and
   the placeholder gives way to --text as soon as there is something there. */
.field{
  background:none;border:0;
  padding:9px 2px;outline:none;text-transform:none;letter-spacing:.04em;
  width:min(74vw,290px);text-align:center;
  transition:color .3s ease;
}
.field::placeholder{
  color:var(--dim);text-transform:uppercase;letter-spacing:var(--tracking);
  transition:color .3s ease;
}
/* On focus the label steps back, because the caret is now saying the same
   thing and saying it better. */
.field:focus::placeholder{color:var(--faint)}
.field--code{text-transform:uppercase;letter-spacing:.42em;width:min(74vw,220px)}
/* Sentences addressed to the reader are not set in caps. The house voice is
   uppercase for identity, labels and data -- but the same words aimed at a
   person read as shouting, which is the wrong tone for anything explanatory
   and badly wrong for anything that failed. */
.say{text-transform:none;letter-spacing:.005em}

/* Feedback reads as a statement, not an alarm: sentence case, and never the
   accent -- that colour means member numbers and live states. */
.err{text-transform:none;letter-spacing:.005em;color:var(--text)}

/* ---------- entrance ----------
   A plain CSS animation, not a class toggled from an effect. The class-based
   version held every line at opacity 0 until React hydrated, so a slow or
   failed hydration left the page blank — and it needed a <noscript> escape
   hatch to work with scripting off at all. An animation with `both` needs
   neither: the copy arrives on its own, JS or no JS. */

.rise{animation:rise .9s cubic-bezier(.2,.8,.2,1) both}
@keyframes rise{
  from{opacity:0;transform:translateY(5px)}
  to{opacity:1;transform:none}
}
.stack > .rise:nth-child(1),.frame .rise{animation-delay:.02s}
.stack > .rise:nth-child(2){animation-delay:.09s}
.stack > .rise:nth-child(3){animation-delay:.16s}
.stack > .rise:nth-child(4){animation-delay:.23s}
.stack > .rise:nth-child(5){animation-delay:.30s}
.stack > .rise:nth-child(6){animation-delay:.37s}
.stack > .rise:nth-child(7){animation-delay:.44s}
.bar.top .rise{animation-delay:.28s}
.bar.bot .rise{animation-delay:.36s}

/* ---------- loader ---------- */

#loader{
  position:fixed;inset:0;z-index:50;background:var(--bg);
  display:grid;place-items:center;
  transition:opacity .85s cubic-bezier(.4,0,.2,1);
}
#loader[data-out='1']{opacity:0;pointer-events:none}
/* 34vmin on a 390px-wide phone is 132px, and the cloud has a couple of
   thousand points in it — so every dot was sub-pixel and the whole mark
   resolved to grey. The cap is what governs on a desktop, where vmin is the
   height; the percentage only bites on a phone, which is where it was
   needed. */
.loader__canvas{width:min(58vmin,240px);aspect-ratio:1}
.loader__meta{
  position:fixed;left:50%;transform:translateX(-50%);bottom:clamp(26px,9vh,74px);
  display:flex;align-items:center;gap:1.1em;color:var(--dim);white-space:nowrap;
}
.loader__bar{width:96px;height:1px;background:var(--hair);position:relative;overflow:hidden}
.loader__bar i{position:absolute;inset:0;background:var(--text);transform-origin:left;transform:scaleX(0)}

/* ---------- small print, foot of a page ---------- */

.foot{bottom:var(--pad)}
.foot > *:first-child{justify-self:start}
.foot > *:last-child{justify-self:end}

@media (max-width:560px){
  :root{--gap:1.35rem}
  .clock,.foot{font-size:11px;gap:.9em}
  /* Every bar keeps its three slots on a phone. Nothing stacks.

     This used to drop the middle slot onto a line of its own, on the
     grounds that the inside nav was a row of links and far too wide. It is
     138 pixels at 320, with seventy-odd to spare beside a name — measured,
     which is what the assumption should have been in the first place. The
     cost of getting it wrong was the nav sitting on a second line hard
     against the bottom edge, under Safari's own toolbar, reading as
     something that had fallen out of the footer rather than part of it. */
  .foot{gap:.75em}
  /* The one thing that can outgrow its slot is a long name in the corner,
     which would run into the centred nav. It gives way rather than
     colliding: the name is a link to a profile, and half of it plus an
     ellipsis still says whose. */
  .foot > *:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ---------- gallery ---------- */

/* The page's name, centred between the date and the time. Its own keyframes
   rather than `rise`: `rise` animates `transform`, and its `to{transform:none}`
   would wipe out the translateX(-50%) doing the centring. */
.page-title{
  position:fixed;top:var(--pad);left:50%;transform:translateX(-50%);z-index:5;
  color:var(--dim);pointer-events:none;white-space:nowrap;
  animation:tuck-in 1s ease .15s both;
}

/* The caption, top left and left-aligned, under the date. It belongs to
   whichever frame is nearest the middle and changes as you scroll, so it wants
   to sit still while the run moves past it — under the frame it read as part
   of the photograph and moved with it.

   One line: the drop, then what it is. `nowrap` because it is a caption and a
   caption that wraps stops being one. No transform here, so the `rise`
   entrance is safe to use. */
.cap{
  position:fixed;left:var(--pad);top:clamp(88px,17vh,158px);z-index:5;
  display:flex;align-items:baseline;gap:.55em;
  pointer-events:none;white-space:nowrap;
}
/* The separator lives on the description, so a frame with no description
   leaves nothing behind -- `:empty` matches the moment the text is cleared. */
.cap__what:empty{display:none}
.cap__what::before{content:'\00b7';margin-right:.55em;color:var(--faint)}

/* The Menu page's run: under the caption, the centred pie's price and what
   is on it. Same corner, same type as the caption; it wraps, because a
   description is a sentence and not a caption. Fixed like the caption so the
   run passes under it. */
.cap-more{
  position:fixed;left:var(--pad);z-index:5;
  top:calc(clamp(88px,17vh,158px) + var(--size) * var(--line));
  width:min(360px,calc(100vw - var(--pad) * 2));
  pointer-events:none;
}
.cap-more__desc{text-wrap:pretty}

.rail{
  position:fixed;inset:0;z-index:1;
  display:flex;align-items:center;gap:clamp(30px,3.6vw,46px);
  overflow-x:auto;overflow-y:hidden;
  padding:0 max(38vw,240px);
  scrollbar-width:none;-ms-overflow-style:none;
  cursor:grab;overscroll-behavior-x:contain;
}
.rail::-webkit-scrollbar{display:none}
.rail figure{
  margin:0;flex:0 0 auto;position:relative;overflow:hidden;background:#141414;
  width:clamp(84px,9vw,116px);height:clamp(112px,15vh,156px);
  transform-origin:50% 50%;will-change:transform,opacity;opacity:.45;
}
.rail img{
  width:100%;height:100%;object-fit:cover;display:block;
  user-select:none;-webkit-user-drag:none;
  filter:grayscale(1) contrast(1.06);
}
.rail figcaption{
  position:absolute;left:6px;bottom:5px;color:#e6e6e6;
  font-size:9px;letter-spacing:.14em;mix-blend-mode:difference;opacity:.55;
}
@media (max-width:700px){
  .rail{padding:0 max(30vw,90px)}
  /* Narrow enough that the two halves will not both fit: keep the line, let
     it run under the edge rather than wrap. */
  .cap{top:clamp(72px,14vh,108px);font-size:12px;right:var(--pad);overflow:hidden}
  .cap-more{top:calc(clamp(72px,14vh,108px) + 12px * var(--line))}
}

/* ---------- choosing: pies and pickup windows ---------- */

.pick{display:flex;flex-direction:column;align-items:stretch;
  width:min(92vw,360px);gap:0}
.pick__label{text-align:center;padding-bottom:.7rem}

/* A row is dim until it is yours. Weight carries the selection, not a box —
   a control with a border would be the loudest thing on the page. */
.row{
  display:grid;grid-template-columns:1fr auto auto;
  align-items:baseline;gap:.9em;
  background:none;border:0;border-top:1px solid var(--hair);
  padding:.72rem .1rem;text-align:left;cursor:pointer;
  color:var(--dim);transition:color .25s ease;
}
.pick .row:last-child{border-bottom:1px solid var(--hair)}
.row:hover:not(:disabled){color:var(--text)}
.row--on{color:var(--text)}
.row--gone{cursor:default;color:var(--faint)}
.row--gone:hover{color:var(--faint)}
.row__name{letter-spacing:var(--tracking)}
.row__meta{font-size:11px;color:var(--faint)}
.row__price{min-width:3.2em;text-align:right}
.row__desc{
  grid-column:1 / -1;font-size:11px;color:var(--faint);
  margin-top:.22rem;line-height:1.5;
}
.row--slot{grid-template-columns:1fr auto}

/* ---------- the receipt ----------
   The one place on the site that is not a centred stack. A receipt is two
   columns with rules between its sections, and that shape holds this
   information better than a column of lines does -- you read down the labels
   or down the values, which is exactly what you want from a record of a thing
   you are going to collect.

   Narrow, like a till roll. Same type, same size, same tokens as everything
   else, so it reads as this site and not as a plugin. */

.bill{
  width:min(92vw,306px);
  border:1px solid var(--hair);
  padding:1.5rem 1.45rem 1.35rem;
  display:flex;flex-direction:column;align-items:stretch;
  text-align:center;
}
.bill__mark{letter-spacing:.14em}
.bill__sub{font-size:11px;margin-top:.2rem}

.bill__rule{height:1px;background:var(--hair);margin:1.05rem 0}
.bill__rule--heavy{background:var(--text);opacity:.5}

.bill__rows{display:flex;flex-direction:column;gap:.42rem;margin:0}
.bill__row{display:flex;justify-content:space-between;align-items:baseline;gap:1.2em}
.bill__row dt{color:var(--dim);text-align:left}
.bill__row dd{margin:0;text-align:right;white-space:nowrap}
/* The pizza is the thing bought, so it is the one line set in the text
   colour rather than the label colour. */
.bill__item{color:var(--text)!important}
.bill__row--total dt,.bill__row--total dd{color:var(--text)}

.bill__who{margin-top:.15rem;letter-spacing:.06em}
.bill__no{font-size:11px;margin-top:.3rem}

.bill__note{
  margin-top:1.15rem;display:flex;flex-direction:column;gap:.45rem;
  font-size:11px;line-height:1.55;
}
.bill__note .t{font-size:11px}
.bill__mock{
  margin-top:1.05rem;padding-top:.85rem;border-top:1px dashed var(--hair);
  font-size:11px;color:var(--faint);
}

/* An iPhone SE is 320 across, and three slots of 11px will not sit in it.
   They shrink rather than wrap — this is the smallest type on the page and
   the alternative is the middle one falling out of the bar again. */
@media (max-width:380px){
  .clock,.foot{font-size:10px;gap:.55em}
}

@media (max-width:560px){
  .bill{width:100%;padding:1.3rem 1.15rem 1.2rem}
}

/* ---------- the mark ----------
   Named `homemark`, not `mark`: `--mark` and `.mark` are the red accent, and
   the logo is not a state. It is the `inline` cut everywhere it appears --
   the characters with no plaque -- so it has no holes and needs no solid
   ground behind it. */

.homemark{display:inline-grid;place-items:center;z-index:6}
.homemark__art{color:var(--dim);transition:color .35s ease}
.homemark:hover .homemark__art{color:var(--text)}

/* Centred on the clock's line, between the date and the time. */
.homemark--top{
  position:fixed;top:var(--pad);left:50%;transform:translateX(-50%);
  animation:tuck-in 1s ease .2s both;
}
/* Centred at the foot. */
.homemark--bottom{
  position:fixed;bottom:var(--pad);left:50%;transform:translateX(-50%);
  animation:tuck-in 1.3s ease .55s both;
}
/* In the stack, so it takes part in the page rather than framing it. */
.homemark--column{margin-bottom:calc(var(--gap) * -.25)}

/* ---------- the preview docks ----------
   Two of them: screens bottom left, variants bottom right. Development
   instrumentation, not part of the site. Styled as instruments on purpose --
   lower-case, 10px, hairline box. If either ever looks like it belongs to the
   design, it has gone wrong. */

.dock,.dock__tab{
  position:fixed;bottom:10px;z-index:80;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:10px;letter-spacing:0;line-height:1.5;text-transform:none;
}
.dock--pages,.dock__tab--pages{left:10px}
.dock--dials,.dock__tab--dials{right:10px}

.dock__tab{
  background:#0d0d0d;border:1px solid var(--hair);color:var(--dim);
  padding:5px 9px;cursor:pointer;display:flex;gap:6px;align-items:center;
  transition:color .2s ease,border-color .2s ease;
}
.dock__tab:hover{color:#e6e6e6;border-color:#2e2e2e}
.dock__key{border:1px solid var(--hair);padding:0 3px;color:var(--faint)}

.dock{
  width:224px;background:#0d0d0d;border:1px solid var(--hair);
  padding:9px 10px 10px;color:var(--dim);
  display:flex;flex-direction:column;gap:9px;
  max-height:calc(100vh - 20px);overflow-y:auto;
}
.dock__head{
  display:flex;justify-content:space-between;align-items:center;
  color:var(--faint);
}
.dock__x{
  background:none;border:0;color:var(--faint);cursor:pointer;
  font-size:13px;line-height:1;padding:0 1px;
}
.dock__x:hover{color:#e6e6e6}

/* A named set of dials, so six rows do not read as one list. */
.dock__group{display:flex;flex-direction:column;gap:5px}
.dock__group-name{
  color:#e6e6e6;opacity:.5;
  border-bottom:1px solid var(--hair);padding-bottom:3px;
}

.dock__row{display:flex;flex-direction:column;gap:4px}
.dock__label{color:var(--faint)}
.dock__opts{display:flex;flex-wrap:wrap;gap:3px}
.dock__opt{
  background:none;border:1px solid var(--hair);color:var(--dim);
  padding:2px 6px;cursor:pointer;font:inherit;letter-spacing:0;
  transition:color .18s ease,border-color .18s ease,background .18s ease;
}
.dock__opt:hover{color:#e6e6e6;border-color:#2e2e2e}
/* The chosen one is filled: on a box this small a colour change alone is easy
   to miss. */
.dock__opt.is-on{background:#e6e6e6;border-color:#e6e6e6;color:#0d0d0d}
/* Where you are now, as distinct from what you have chosen. */
.dock__opt.is-here{color:var(--mark);border-color:#3a1a14}

.dock__foot{
  display:flex;align-items:center;gap:7px;
  border-top:1px solid var(--hair);padding-top:8px;
}
.dock__note{color:var(--faint);flex:1;line-height:1.35}

/* The docks keep their own palette in light mode -- an instrument should not
   restyle itself with the thing it is inspecting. */
@media (max-width:620px){
  .dock{width:calc(100vw - 20px)}
  .dock--pages,.dock--dials{left:10px;right:10px}
}


/* ---------- the count ----------
   `18/25`. One line, the same size as everything else — the number is not a
   headline, and the bar that used to sit under it was the only non-text
   element on a page made of text. */

.count{display:inline-flex;align-items:baseline;gap:.06em}
.count__n{display:inline-block;text-align:right}
.count__sep,.count__of{letter-spacing:var(--tracking)}

/* ---------- the invitation ----------
   One link and an allowance. The URL is set as a URL and never spaced out
   like a passcode -- it is not something anybody types. */

.invite{
  display:flex;flex-direction:column;align-items:center;gap:1.15rem;
  width:min(94vw,400px);
}
.invite__url{
  font-size:12px;text-transform:none;letter-spacing:.01em;
  color:var(--text);text-align:center;word-break:break-all;line-height:1.6;
}
.invite__row{display:flex;align-items:baseline;gap:1.6em}
.invite__ask{gap:.85rem}
.invite__plain{
  background:none;border:0;cursor:pointer;padding:0;
  font-size:11px;color:var(--faint);transition:color .25s ease;
}
.invite__plain:hover{color:var(--dim)}

@media (max-width:560px){ .invite{width:100%} }

/* A pasted link, not a typed passcode: normal spacing, wider, left-aligned
   text would wrap badly so it scrolls instead. */
.field--link{
  text-transform:none;letter-spacing:.01em;
  width:min(84vw,330px);font-size:12px;
}
/* A field you type words into, not a passcode. */
.field--say{text-transform:none;letter-spacing:.01em}
/* A button that should read as a line of copy. */
.plain{background:none;border:0;cursor:pointer;padding:0}

/* ---------- inside: where the navigation sits ----------
   Two of the three arrangements take it out of the centre column, which is
   what frees the middle of the page for the drop itself. */

.nav{display:flex;z-index:5;animation:tuck-in .9s ease .5s both}
/* In the bottom bar, as its middle slot — so it is aligned and sized by the
   bar rather than positioned against it. */
.nav--foot{gap:2.1em;justify-content:center;white-space:nowrap}
/* Up the right-hand side, the quietest of the three. */
.nav--edge{
  position:fixed;top:var(--pad);right:var(--pad);
  flex-direction:column;align-items:flex-end;gap:.5em;
}
/* The time is on that line too, so the column starts below it. */
.nav--edge{padding-top:1.95rem}

/* `edge` also moves the column itself off the centre line — the whole point
   of the variant is that the page is allowed to have corners. */
.stack--edge{
  align-items:flex-start;text-align:left;
  padding-left:max(var(--pad),7vw);padding-right:max(var(--pad),34vw);
}
.stack--edge .group{align-items:flex-start}
.stack--edge .pick__label,.stack--edge .invites__count{text-align:left}

@media (max-width:700px){
  .nav--foot{gap:1.5em}
  .nav--edge{
    left:var(--pad);flex-direction:row;justify-content:center;align-items:baseline;
    gap:1.6em;padding-top:1.9rem;
  }
  .stack--edge{align-items:center;text-align:center;padding-left:var(--pad);padding-right:var(--pad)}
  .stack--edge .group{align-items:center}
}
/* The menu lists the same rows as the claim screen but nothing is clickable,
   so they do not light up or take a pointer. */
.row--flat{grid-template-columns:1fr auto;cursor:default;color:var(--dim)}
.row--flat:hover{color:var(--dim)}

/* ---------- the record ----------
   The profile, and the only page behind the door that is left-aligned. It is
   a record rather than an offer, and a record reads down a column of labels;
   centring it would make it look like another thing to act on. */

.sheet{align-items:flex-start;text-align:left;
  padding-left:max(var(--pad),8vw);padding-right:max(var(--pad),8vw)}
.sheet > .rise{width:min(94vw,340px)}
.sheet__head{display:flex;flex-direction:column;gap:.3rem}
.sheet__name{letter-spacing:.06em}
.sheet__rows{display:flex;flex-direction:column;gap:.62rem;margin:0}
.sheet__row{
  display:grid;grid-template-columns:7.5em 1fr;align-items:baseline;gap:1em;
  border-top:1px solid var(--hair);padding-top:.6rem;
}
.sheet__row dt{font-size:11px}
.sheet__row dd{margin:0;text-transform:none;letter-spacing:.01em}
.sheet .say{max-width:34ch}

@media (max-width:560px){
  .sheet{padding-left:var(--pad);padding-right:var(--pad)}
  .sheet__row{grid-template-columns:6.5em 1fr}
}
/* The credit along the bottom edge, when it is not in the column.
   Deliberately *not* quieter than the bar at the top: it inherits `.foot`,
   which is the same size, tracking and colour as `.clock`. It was `--faint`,
   which made the two ends of the same page two different kinds of small
   print — the date at the top and the byline at the bottom are one voice. */
.foot--credit{animation:tuck-in 1.2s ease .6s both}

/* `Drop 001 | 10.17.26` — one fact, one line. */
.dropline{display:inline-flex;align-items:baseline;gap:.62em;white-space:nowrap}
.dropline__bar{font-size:11px;transform:translateY(-.03em)}

/* ---------- the tally ----------
   What you have picked so far, in the shape of the receipt you are about to
   get. Showing the same three rows before and after confirming means the
   confirm button holds no surprises — you have already read the thing it is
   going to hand you.

   Its own entrance rather than `rise`: `rise` takes its delay from
   nth-child in the stack, and this appears on a tap, where a third of a
   second of nothing reads as the tap not having landed. */
.tally{
  width:min(92vw,360px);margin:0;
  display:flex;flex-direction:column;gap:.5rem;
  border-top:1px solid var(--hair);padding-top:.85rem;
  animation:tally-in .42s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes tally-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
.tally__row{display:flex;justify-content:space-between;align-items:baseline;gap:1.2em}
.tally__row dt{color:var(--dim)}
.tally__row dd{margin:0;text-align:right;white-space:nowrap}
.tally__row--total{
  border-top:1px solid var(--hair);padding-top:.5rem;margin-top:.1rem;
}
.tally__row--total dt,.tally__row--total dd{color:var(--text)}
.tally__waiting{color:var(--faint)}

/* ---------- the status light ----------
   In the footer of every screen behind the door, because the drop being on is
   true of the whole place rather than of one page. A dot and a word: the dot
   reads at a glance without being read, which is what a status is for. */

.status{display:inline-flex;align-items:baseline;gap:.85em;white-space:nowrap}
.status__on{display:inline-flex;align-items:baseline;gap:.5em}
.status__dot{
  width:5px;height:5px;border-radius:50%;background:currentColor;
  align-self:center;flex:0 0 auto;
}
/* Only the live one pulses. A dot breathing next to `Sold out` would be
   saying something is happening when nothing is. */
.status.live .status__dot{animation:status-pulse 2.4s ease-in-out infinite}
@keyframes status-pulse{0%,100%{opacity:1}50%{opacity:.35}}
.status.dim .status__dot{background:var(--faint)}
@media (prefers-reduced-motion:reduce){
  .status.live .status__dot{animation:none}
}

.sheet__out{padding-top:.2rem}
/* Two facts on one line: how many are left, and whether you can have one. */
.tape{display:inline-flex;align-items:baseline;gap:1.05em;white-space:nowrap}
.foot__house{display:inline-flex;align-items:center;gap:.72em}

/* ---------- forms ----------
   Close together. The fields carry their own padding, so a rem of gap on top
   of that spread four lines of type over most of the screen. */

.form{display:flex;flex-direction:column;align-items:center;gap:.1rem}
.form .field{animation:tally-in .34s cubic-bezier(.2,.8,.2,1) both}
.form__go{margin-top:1.1rem}
.form__err{margin-top:.8rem}
.form__alt{margin-top:1.15rem}
.form__note{margin-bottom:.9rem}
/* Copy and Share side by side. Share is only there when the browser has a
   share sheet, which is most phones and few desktops. */
.invite__acts{display:flex;align-items:baseline;gap:1.9em;flex-wrap:wrap;justify-content:center}

/* ---------- pickup windows as chips ----------
   A time is three characters wide. A column of six of them spent most of the
   screen's height saying almost nothing, and pushed the total below the fold
   on a phone — which is the one line you want in view when you commit. */

.slots{display:flex;flex-direction:column;align-items:stretch;width:min(92vw,360px)}
.slots__row{display:flex;flex-wrap:wrap;gap:.5rem;justify-content:center}
.chip{
  background:none;border:1px solid var(--hair);color:var(--dim);
  padding:.42rem .72rem;cursor:pointer;font:inherit;
  letter-spacing:var(--tracking);
  transition:color .2s ease,border-color .2s ease;
}
.chip:hover:not(:disabled){color:var(--text);border-color:#2e2e2e}
/* The chosen one takes a border in the text colour rather than a fill: a
   filled chip would be the loudest thing on the screen, and the rows above
   it carry selection by weight alone. */
.chip--on{color:var(--text);border-color:var(--text)}
.chip--gone{color:var(--faint);cursor:default;border-color:var(--hair)}
.chip--gone:hover{color:var(--faint)}

@media (max-width:560px){ .slots{width:100%} }

/* ---------- filling a form ----------
   While you are typing, the page narrows to the field you are in: everything
   else drops to a whisper and the field itself slides to the middle. Then the
   moment the form is complete it all comes back, because the point of
   narrowing was to get you here.

   Dimmed, never hidden. `display:none` would collapse the layout and throw
   the very field you are looking at across the screen — the whole effect
   depends on nothing moving except by design. */

.form{transition:transform .62s cubic-bezier(.22,.9,.2,1)}

/* Everything in the stack that is not the form. The form is inside a wrapper
   div in each page, so this reaches the wrapper and lets the form itself
   through. */
/* `!important` here is load-bearing and not laziness. Almost everything on
   these pages carries `.rise`, whose animation has `fill-mode: both` — and a
   filled animation outranks every normal declaration in the cascade, so its
   `to{opacity:1}` pins the copy at full brightness for ever. An important
   declaration is the one thing that still beats it. (The same fill-mode is
   why `.rise` cannot be used on anything positioned with a transform.) */
body[data-focus='1'] .stack > *{
  opacity:.12 !important;
  transition:opacity .55s ease;
  pointer-events:none;
}
body[data-focus='1'] .stack > *:has(.form){opacity:1 !important;pointer-events:auto}
/* Fixed furniture recedes with the rest. */
body[data-focus='1'] .clock,
body[data-focus='1'] .foot,
body[data-focus='1'] .homemark,
body[data-focus='1'] .nav{opacity:.12 !important;transition:opacity .55s ease}

.stack > *{transition:opacity .55s ease}
.clock,.foot,.homemark,.nav{transition:opacity .55s ease}

/* Inside the form: the field you are in, and the ones you are not. */
.form--narrow .field{opacity:.16 !important;transition:opacity .5s ease,color .3s ease}
.form--narrow .field.is-live{opacity:1 !important}
.form--narrow .form__go,
.form--narrow .form__alt,
.form--narrow .form__note{opacity:.12 !important;transition:opacity .5s ease;pointer-events:none}

@media (prefers-reduced-motion:reduce){
  /* The dimming is the useful half and it costs nothing to keep; only the
     sliding is motion anybody could object to, and the transform is already
     held at zero in that case. */
  .form{transition:none}
}
/* What to do about a booked pickup: where it is, and a way to not forget. */
.booked{display:flex;flex-direction:column;align-items:center;gap:1.05rem;margin-top:1.15rem}
.booked a{text-align:center}

/* Editing the record. The fields sit in the value column, so a row reads the
   same whether it is being read or written. */
.field--inline{
  width:100%;text-align:left;padding:0;
  border-bottom:1px solid var(--hair);
}
.field--inline:focus{border-color:var(--text)}
.sheet__edit{
  display:flex;align-items:baseline;gap:1.7em;
  margin-top:1.15rem;flex-wrap:wrap;
}
.sheet__err{margin-top:.85rem}

/* The front page carries three or four lines and nothing else, so it can
   afford to sit closer together than a screen with lists on it. */
.stack--tight{gap:1.05rem}
/* Credit at the edges means the column is only the drop and the door. */
/* The front page with the credits in the corners: name, drop, and the one
   thing to do. Tighter than the default stack — three lines that are one
   thought should read as a block, not as three offers to weigh. */
.stack--bare{gap:.62rem}

/* The consent tick. Small, because it is a legal necessity and not a feature
   — but never hidden, since a disclosure nobody can read is not a disclosure. */
.tick{
  display:flex;align-items:flex-start;gap:.7em;
  width:min(84vw,320px);margin-top:1rem;cursor:pointer;
}
.tick input{
  appearance:none;-webkit-appearance:none;
  width:12px;height:12px;flex:0 0 auto;margin-top:.3em;
  border:1px solid var(--dim);background:none;cursor:pointer;
  transition:background .2s ease,border-color .2s ease;
}
.tick input:checked{background:var(--text);border-color:var(--text)}
/* `--dim`, not `--faint`. This is the exact wording somebody is agreeing to,
   recorded in `sms_consent_text` and producible later as the defence if a
   text is ever challenged — consent that cannot comfortably be read is not
   much of a record of anything. */
.tick__text{font-size:11px;line-height:1.5;color:var(--dim);text-align:left}
.tick:hover .tick__text{color:var(--dim)}
/* Name and number on one line, the number quieter than the name. */
.sheet__head{display:flex;align-items:baseline;gap:1.1em;flex-wrap:wrap}
.sheet__no{color:var(--dim);font-size:11px}
/* Edit, then sign out under it. */
.sheet__acts{display:flex;flex-direction:column;align-items:flex-start;gap:1.05rem;margin-top:1.15rem}
.sheet__acts .sheet__edit{margin-top:0}

/* ---------- room for the bars ----------
   Both bars are fixed, so a page long enough to scroll ran its first and last
   lines underneath them. The stack already reserved space at the foot; it
   needs the same at the head, and enough for the bottom bar to wrap to two
   rows on a narrow screen. */
.stack{
  padding-top:calc(var(--pad) * 2.6);
  padding-bottom:calc(var(--pad) * 4.2);
}
@media (max-width:560px){
  .stack{padding-bottom:calc(var(--pad) * 5.4)}
}
/* The bars sit on their own ground so text scrolling under them does not
   show through. A hard edge would read as a rule; this fades out. */
.clock::before,.foot::before{
  content:'';position:absolute;left:calc(var(--pad) * -1);right:calc(var(--pad) * -1);
  height:calc(100% + var(--pad) * 1.7);z-index:-1;pointer-events:none;
}
.clock::before{top:calc(var(--pad) * -1);
  background:linear-gradient(to bottom,var(--bg) 62%,transparent)}
.foot::before{bottom:calc(var(--pad) * -1);
  background:linear-gradient(to top,var(--bg) 62%,transparent)}
/* Apple or Google, side by side. */
.cal{display:flex;align-items:baseline;gap:1.9em;flex-wrap:wrap;justify-content:center}
/* One more row of windows, in the same rhythm as the rest of the list. */
.row--more{grid-template-columns:1fr;justify-items:center;cursor:pointer}
.row--more:hover .row__name{color:var(--text)}
/* Once both are chosen the tally is the whole screen, so it can breathe. */
.tally--sole{border-top:0;padding-top:0}
.tally--sole .tally__row{font-size:14px}
.tally__change{margin-top:1.1rem;align-self:center;font-size:11px}

/* ---------- tonight ----------
   The counter screen. Grouped by window, because that is the order people
   arrive in and the only structure worth holding in your head at a door. */
.night{display:flex;flex-direction:column;gap:1.5rem;width:min(94vw,420px)}
.night__window{display:flex;flex-direction:column}
.night__at{padding-bottom:.45rem}
.night__row{color:var(--text)}
.night__row:hover:not(:disabled){color:var(--text)}
.night__row .row__meta{color:var(--dim)}
@media (max-width:560px){ .night{width:100%} }
/* The two switches on the profile: in the value column, so a row reads the
   same whether it holds a fact or a choice. */
.sheet__prefs{margin-top:.2rem}
.tick--inline{width:auto;margin-top:0}
.tick--inline .tick__text{color:var(--text)}
.tick--inline:hover .tick__text{color:var(--text)}

/* ---------- printing ----------
   Confirming used to swap one static screen for another. Now the receipt
   comes out: a stepped wipe down the box, because a printer feeds in
   increments and a smooth slide reads as a slide. The rows are already in
   place and are simply uncovered, band by band, the way a real one appears.

   `both` holds the finished state, so a re-render cannot leave it half fed. */

.bill--print{
  animation:print 1.15s steps(15, end) both;
}
@keyframes print{
  from{clip-path:inset(0 0 100% 0)}
  to{clip-path:inset(0 0 0 0)}
}

/* The action arrives once the paper has stopped. Mounted by the component
   when the printing is done, so this only has to fade it in. */
.bill__after{animation:tuck-in .5s ease both}

/* The wait. Same 96px hairline the loader uses, so the wait and the arrival
   belong to the same site — sliding, not filling, because it does not know
   how long the server will take and a bar that pretends to is lying. */
.feed{
  display:block;width:96px;height:1px;background:var(--hair);
  position:relative;overflow:hidden;margin-top:1.1rem;
}
.feed i{
  position:absolute;top:0;bottom:0;width:40%;background:var(--text);
  animation:feed 1s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes feed{
  from{transform:translateX(-100%)}
  to{transform:translateX(250%)}
}

@media (prefers-reduced-motion:reduce){
  /* The receipt still arrives; it just does not perform. */
  .bill--print{animation:none;clip-path:none}
  .bill__after{animation:none}
  .feed i{animation:none;width:100%}
}

/* ---------- the way to reach a person ----------
   Was a byline that swapped two names for the address on hover. The names
   came off the public pages, so there is nothing left to swap and nothing
   left to hide behind — the address is simply the thing in the corner. */
.makers{color:inherit;transition:color .3s ease}
.makers:hover{color:var(--text)}

/* ---------- the light switch ----------
   In the same slot as the time, and invisible until the bar is hovered. A
   preference is not navigation and should not cost one of the four lines
   this page has. */
/* The bar itself is `pointer-events:none` so it never eats a click meant for
   the page — which also means `.clock:hover` can never match, because a
   thing that is not hit-tested is never hovered. The reveal hangs off this
   wrapper instead, which opts back in. Hovering the time shows the switch. */
.clock__end{
  display:inline-flex;align-items:baseline;gap:.75em;justify-self:end;
  pointer-events:auto;
}
.themer{
  position:relative;
  display:inline-flex;align-items:center;justify-content:center;
  width:10px;height:10px;color:var(--dim);
  background:none;border:0;padding:0;cursor:pointer;
  opacity:0;transition:opacity .3s ease,color .3s ease;
  transform:translateY(.08em);
}
/* A ten-pixel target is a ten-pixel target. This gives it the reach of a
   button without giving it the width of one, which would move the time. */
.themer::before{content:'';position:absolute;inset:-7px}
.clock__end:hover .themer,
.themer:focus-visible{opacity:1}
.themer:hover{color:var(--text)}
/* On a touch screen "reveals on hover" means "is not there", so it stays —
   but quietly. At half opacity it read as an unexplained glyph parked beside
   the clock; at a quarter it is a mark you notice only when looking for one,
   which is the whole intent. */
@media (hover:none){.themer{opacity:.26}}
@media (hover:none){.themer:active{opacity:1}}

/* ---------- small print that is smaller ---------- */
.say--small{font-size:11px}

/* For the half of a label that only a screen reader needs. */
.vh{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}

/* ---------- the slice, standing alone ----------
   Square, and sized by whoever puts it on a page. */
.slice{aspect-ratio:1;display:block}

/* The page that is not there. A little more air around the animation than
   the front page's stack wants, and the mark above it rather than beside. */
.lost{gap:1.15rem}
.lost .slice{margin:.2rem 0 .1rem}

/* ---------- arriving on an invitation ----------
   Three blocks, revealed in the order somebody would say them. The lift is a
   transform on the container: the blocks hold their space from the first
   frame, so nothing reflows and the house drifts up rather than jumping. */
.intro{
  display:flex;flex-direction:column;align-items:center;row-gap:1.15rem;
  transition:transform .95s cubic-bezier(.22,.9,.24,1);
}
/* Before the measurement lands there is nothing worth showing. */
.intro[data-ready='0']{visibility:hidden}

.intro__house,
.intro__said,
.intro__form{
  opacity:0;
  transform:translateY(6px);
  transition:opacity .85s ease,transform .85s cubic-bezier(.2,.8,.2,1);
}
.intro[data-ready='1'] .intro__house{opacity:1;transform:none}
.intro[data-stage='1'] .intro__said,
.intro[data-stage='2'] .intro__said{opacity:1;transform:none}
.intro[data-stage='2'] .intro__form{opacity:1;transform:none}

/* Nothing below the house can be reached before it is offered. `opacity` on
   its own leaves the form's first field focusable and, on iOS, able to take
   the keyboard from behind an invisible layer. */
.intro__said,
.intro__form{visibility:hidden}
.intro[data-stage='1'] .intro__said,
.intro[data-stage='2'] .intro__said,
.intro[data-stage='2'] .intro__form{visibility:visible}

@media (prefers-reduced-motion:reduce){
  .intro,.intro__house,.intro__said,.intro__form{transition:none}
}

/* ---------- the way back in ----------
   In the footer's middle slot, in the footer's own voice: it inherits
   `.foot` entirely, so the size, tracking and colour are the byline's and
   the city's rather than a third treatment. Hidden until the bar is hovered
   — the front page's job is to say this exists, not to recruit, and anybody
   who already has an account knows to look. */
.foot__in{
  opacity:0;
  transition:opacity .3s ease,color .3s ease;
}
.foot:hover .foot__in,
.foot__in:focus-visible{opacity:1}
.foot__in:hover{color:var(--text)}
/* Nothing to hover with, so it sits quiet instead of invisible. */
@media (hover:none){.foot__in{opacity:.5}}

/* ===========================================================================
   The back office
   ===========================================================================
   The same voice as the rest of the site and a different posture. The public
   pages are four lines in the middle of a screen; this is a tool that gets
   read at a counter with one hand, so it is aligned left, dense, and spends
   its width on rows rather than on air. */

.ops{
  max-width:940px;margin:0 auto;
  /* Room at the foot for a nav that wraps to two rows on a phone. It used
     to end under it. */
  padding:calc(var(--pad) * 2.6) var(--pad) calc(var(--pad) * 5.2);
  display:flex;flex-direction:column;gap:2.4rem;
}

.ops__block{display:flex;flex-direction:column;gap:.9rem}
.ops__h{color:var(--dim)}
.ops__lede{font-size:15px}
.ops__act{margin-top:.35rem}

/* ---------- the numbers ----------
   A grid that fills, so a row is never one tile wide with dead space beside
   it. `auto-fit` rather than a fixed count: the same block reads as four
   across on a laptop and two on a phone without a breakpoint. */
.tiles{
  display:grid;gap:1px;
  grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
}
/* The hairlines are a ring on each tile rather than a filled gap behind the
   grid. Painting the container and letting the 1px gaps show through is one
   declaration shorter and draws a solid grey block wherever the last row is
   short of tiles — eight numbers in a grid of three leaves a hole, and the
   hole was the loudest thing on the screen. */
.tile{
  background:var(--bg);padding:.85rem .95rem 1rem;
  box-shadow:0 0 0 1px var(--hair);
  display:flex;flex-direction:column;gap:.15rem;
}
.tile__k{font-size:10px;letter-spacing:.13em;color:var(--faint)}
.tile__v{font-size:21px;line-height:1.3;font-variant-numeric:tabular-nums}
/* Not the accent, which means a total you owe and a code you say — this is
   the one number that is genuinely a warning, so it gets the accent and
   nothing else does. */
.tile__v--bad{color:var(--mark)}
.tile__n{font-size:10px;letter-spacing:.04em}

/* The nav carries six items rather than three, so it wraps rather than
   overflowing, and it is the middle slot of the footer like the member one. */
.opsnav{display:flex;flex-wrap:wrap;gap:.2rem 1.05em;justify-content:flex-end}
.opsnav .is-here{color:var(--text)}

.live{color:var(--live)}

@media (max-width:560px){
  .ops{padding-top:calc(var(--pad) * 3.2);gap:1.8rem}
  .tiles{grid-template-columns:repeat(auto-fit,minmax(118px,1fr))}
  .tile__v{font-size:18px}
}

/* ---------- a list of things you act on ----------
   One hairline between rows rather than a box around each: a list is one
   object, and a border per row reads as a stack of unrelated cards. */
.rows{display:flex;flex-direction:column;border-top:1px solid var(--hair)}
.row2{
  display:flex;align-items:baseline;gap:1em;
  padding:.72rem .1rem .8rem;
  border-bottom:1px solid var(--hair);
}
.row2[data-done='1'] .row2__k{color:var(--dim)}
.row2__main{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}
.row2__k{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row2__meta{font-size:10px;letter-spacing:.04em}
.row2__tail{font-size:10px;letter-spacing:.06em;white-space:nowrap;flex:none}
.row2__go{flex:none}

/* The minted link. Wraps, because it is a URL and a phone is narrow, and it
   is a button because its whole job is to end up on a clipboard. */
.row2__link{
  margin-top:.3rem;font-size:11px;letter-spacing:.02em;text-transform:none;
  color:var(--text);background:none;border:0;padding:0;cursor:pointer;
  text-align:left;word-break:break-all;
}
.row2__link:hover{color:var(--dim)}

/* An address is data, not voice: the site shouts, and an email address that
   has been shouted at somebody reads as a different address. */
.addr{text-transform:none;letter-spacing:.01em}

/* ---------- money ---------- */

/* Not an error and not decoration: something is true that makes every number
   under it wrong, and it has to be read before them. */
.warn{
  color:var(--text);border-left:2px solid var(--mark);
  padding:.55rem 0 .55rem .85rem;max-width:58ch;
}
.warn em{font-style:normal;color:var(--dim)}

/* A currency field. The sign is outside the input so it cannot be deleted,
   and the input is sized to the number rather than the row. */
.cost{display:inline-flex;align-items:baseline;gap:.25em;flex:none}
.cost__cur{font-size:11px}
.cost__in{
  width:4.6em;background:none;border:0;border-bottom:1px solid var(--hair);
  color:var(--text);font:inherit;font-size:13px;letter-spacing:.02em;
  text-align:right;padding:0 0 .12rem;
}
.cost__in:focus{outline:none;border-bottom-color:var(--text)}

/* Adding a line to the books. Wraps on a phone rather than scrolling. */
.spend{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:.6rem .8rem;
  padding:.3rem 0 1rem;
}
.spend__what{flex:1 1 11rem;min-width:0;font-size:13px;text-align:left}
.spend__err{flex:1 1 100%}
.pick2{
  background:none;border:0;border-bottom:1px solid var(--hair);
  color:var(--dim);font:inherit;font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;padding:0 0 .12rem;cursor:pointer;
}
.pick2:focus{outline:none;border-bottom-color:var(--text)}

/* ---------- the counter ----------
   The running totals stay on screen while you work down the list: what is
   left to hand over, what has been taken, and what is owed. The third only
   appears when it is not zero, because a nought beside the word `owed` reads
   as a problem rather than its absence. */
.tally{
  display:flex;flex-wrap:wrap;gap:.3rem 1.4em;
  padding:.65rem 0 .9rem;border-bottom:1px solid var(--hair);
  font-size:11px;letter-spacing:.1em;color:var(--dim);
}
.tally b{font-weight:400;color:var(--text);font-size:15px;letter-spacing:.02em}
.tally .mark b{color:var(--mark)}

/* Two buttons, because at a counter the pizza going across and the money
   coming back are one action. Picked-up-then-paid as two steps is one step
   somebody forgets. */
.pay{display:inline-flex;gap:.55em;flex:none}

/* The rare things. Behind a tap, so cancelling does not sit next to the
   button pressed forty times a night. */
.more{
  display:flex;flex-direction:column;align-items:flex-start;gap:.4rem;
  padding:.6rem 0 .2rem;
}
.more__move{display:inline-flex;align-items:baseline;gap:.6em;font-size:11px;letter-spacing:.1em}
.plain{background:none;border:0;padding:0;cursor:pointer;font:inherit;text-align:left}

/* Moving a drop's status. The state it is in is text; the others are the
   things you can do, which is the right way round — a row of toggles makes
   you work out which one is current. */
.states{display:flex;flex-wrap:wrap;align-items:baseline;gap:.4rem 1em}
.states__now{font-size:11px;letter-spacing:.1em}

/* Finding somebody. Left-aligned and full width — it is a tool, not a
   centred prompt. */
.find{
  text-align:left;font-size:13px;width:100%;max-width:22rem;
  border-bottom:1px solid var(--hair);padding-bottom:.2rem;
}
.find:focus{border-bottom-color:var(--text)}
.more__notes .field{text-align:left;font-size:12px;width:12rem;max-width:100%}

/* ---------- the agent door ----------
   The invitation's one instruction and its folded-away list of ways in, the
   note for agents at the foot of the public pages, and the desk — the plain
   forms a browser agent books through. */

.door{
  display:flex;flex-direction:column;align-items:center;gap:.35rem;
  width:min(94vw,420px);
}
.door__said{max-width:34ch;margin-bottom:.6rem}
.door__url{
  margin-top:.9rem;
  font-size:12px;text-transform:none;letter-spacing:.01em;
  word-break:break-all;line-height:1.6;
}
.door__acts{display:flex;gap:1.6em;align-items:baseline}
.door__more{margin-top:1.4rem;width:100%}
.door__more summary{list-style:none;cursor:pointer;display:inline-block}
.door__more summary::-webkit-details-marker{display:none}
.door__list{
  margin-top:1rem;display:grid;grid-template-columns:1fr;gap:.2rem;text-align:left;
}
.door__list dt{color:var(--dim);margin-top:.9rem}
.door__list dd{display:flex;flex-direction:column;align-items:flex-start;gap:.15rem}
.door__code{
  display:block;font-size:11px;letter-spacing:.01em;color:var(--text);
  word-break:break-all;line-height:1.55;
}
.door__note{margin-top:1.4rem;font-size:11px}

.stack .agentline{font-size:11px;color:var(--faint)}
.stack .agentline a{color:var(--dim)}

.agentnote{
  max-width:560px;margin:0 auto;
  padding:0 var(--pad) calc(var(--pad) * 4);
  font-size:11px;line-height:1.7;color:var(--faint);text-align:left;
}
.agentnote strong{font-weight:400;color:var(--dim)}
.agentnote a,.agentnote code{color:var(--dim);word-break:break-all;font-family:inherit}

.desk{
  max-width:640px;margin:0 auto;
  padding:calc(var(--pad) * 1.4) var(--pad) calc(var(--pad) * 3);
  display:flex;flex-direction:column;gap:2.2rem;
}
.desk h2,.desk h3{font-size:var(--size);font-weight:400;text-transform:uppercase;letter-spacing:var(--tracking)}
.desk h3{color:var(--dim);margin-top:1rem}
.desk section{display:flex;flex-direction:column;gap:.7rem}
.desk__head{display:flex;flex-direction:column;gap:.4rem}
.desk__head code,.desk code{font-family:inherit;word-break:break-all}
.desk__flash{border-left:2px solid var(--live);padding-left:.9em;white-space:pre-wrap}
.desk__flash--no{border-left-color:var(--mark)}
.desk__terms{border-left:1px solid var(--hair);padding-left:.9em;display:flex;flex-direction:column;gap:.6rem;color:var(--dim)}
.desk form{display:flex;flex-direction:column;gap:.75rem;align-items:flex-start}
.desk label{display:flex;flex-direction:column;gap:.2rem;width:100%}
.desk fieldset{border:0;display:flex;flex-direction:column;gap:.35rem}
.desk legend{color:var(--dim);margin-bottom:.3rem}
.desk input:not([type]),.desk input[type=email],.desk input[type=tel],.desk input[type=text],.desk textarea,.desk select{
  font:inherit;color:var(--text);background:transparent;
  border:0;border-bottom:1px solid var(--hair);padding:.3em 0;width:100%;
  text-transform:none;letter-spacing:.01em;
}
.desk textarea{border:1px solid var(--hair);padding:.5em}
.desk input:focus,.desk textarea:focus,.desk select:focus{outline:none;border-color:var(--dim)}
.desk__check{flex-direction:row !important;align-items:baseline;gap:.6em !important}
.desk button{
  font:inherit;color:var(--text);background:none;border:1px solid var(--hair);
  padding:.45em 1.1em;cursor:pointer;text-transform:uppercase;letter-spacing:var(--tracking);
}
.desk button:hover{border-color:var(--text)}
.desk__facts{display:grid;grid-template-columns:9em 1fr;gap:.25rem 1rem}
.desk__facts dt{color:var(--dim)}
.desk a{text-decoration:underline;text-decoration-color:var(--hair);text-underline-offset:3px}
.desk__foot{font-size:11px}

/* The prose pages: privacy, terms. */
.prose{
  max-width:620px;margin:0 auto;
  padding:calc(var(--pad) * 2.6) var(--pad) calc(var(--pad) * 4);
  display:flex;flex-direction:column;gap:1rem;
}
.prose h1,.prose h2{font-size:var(--size);font-weight:400;text-transform:uppercase;letter-spacing:var(--tracking)}
.prose h2{margin-top:1.2rem;color:var(--dim)}
.prose ul{padding-left:1.1em;display:flex;flex-direction:column;gap:.35rem}
.prose a{text-decoration:underline;text-decoration-color:var(--hair);text-underline-offset:3px}

/* ---------- back office: the door and the prep sheet ---------- */
.ops__form{display:flex;flex-direction:column;align-items:flex-start;gap:.5rem;max-width:420px}
.ops__form .field{width:100%;text-align:left}
.ops__made{display:flex;flex-direction:column;gap:.4rem;border-left:2px solid var(--live);padding-left:.9em;margin:.6rem 0 1rem;max-width:520px}
.labels{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin-top:1rem}
.label{border:1px solid var(--hair);padding:14px 16px;display:flex;flex-direction:column;gap:.15rem;break-inside:avoid}
.label__name{font-size:18px;letter-spacing:.06em}
.label__warn{color:var(--mark)}
.label__thanks{margin-top:.5rem;color:var(--dim)}
@media print{
  :root{--bg:#fff;--text:#000;--dim:#555;--hair:#000;--mark:#000}
  .clock,.foot,.noprint,.opsnav{display:none !important}
  .ops{padding:0 !important}
  .labels{grid-template-columns:repeat(2,1fr)}
  .label{page-break-inside:avoid}
}

/* ===========================================================================
   Joining, one question at a time
   ===========================================================================
   The old shape put all three fields on the page and dimmed the ones you
   were not in to sixteen per cent, which made a field that had just appeared
   almost invisible — the form read as empty rather than as having moved on.
   Dimming an answer is only legible if you already know it is there.

   So an answered question steps back to a small line that is still readable
   and can be tapped to correct, and the question you are on is the only
   thing at full size. */

.ask{
  display:flex;flex-direction:column;align-items:center;
  width:min(90vw,340px);
}

/* What has been answered. Quiet, not hidden — `--dim` for the label and full
   text colour for the answer, because the answer is the part you check. */
.ask__was{
  display:flex;align-items:baseline;gap:.8em;
  width:100%;justify-content:center;
  padding:.3rem 0;font-size:11px;letter-spacing:.1em;
  animation:tally-in .4s cubic-bezier(.2,.8,.2,1) both;
}
.ask__wask{font-size:10px}
.ask__wasv{color:var(--text);text-transform:none;letter-spacing:.02em;font-size:12px}
.ask__was:hover .ask__wasv{color:var(--dim)}

/* The question you are on. Keyed on the step, so React remounts it and the
   animation plays again each time rather than once on arrival. */
.ask__now{
  display:flex;flex-direction:column;align-items:center;width:100%;
  margin-top:1.15rem;
  animation:ask-in .5s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes ask-in{
  from{opacity:0;transform:translateY(10px)}
  to{opacity:1;transform:none}
}

/* The question is a sentence, and it stays put while you type — a
   placeholder disappears exactly when you start typing and want it most. */
.ask__q{margin-bottom:.5rem;color:var(--text)}
.ask__in{
  font-size:17px;width:100%;
  border-bottom:1px solid var(--hair);
  transition:border-color .3s ease;
}
.ask__in:focus{border-bottom-color:var(--text)}
.ask__why{font-size:10px;letter-spacing:.04em;margin-top:.55rem;max-width:26ch;text-align:center}
.ask__back{margin-top:.9rem}
.ask .tick{margin-top:1.2rem}

@media (prefers-reduced-motion:reduce){
  .ask__now,.ask__was{animation:none}
}

/* ---------- the front page's one action ----------
   One instruction and a [Copy]. The message is never shown. */
.askagent{display:flex;flex-direction:column;align-items:center;gap:.45rem;margin-top:.4rem}
.askagent__how{max-width:min(46ch,92vw);word-break:break-word}
.askagent__copy{font-size:var(--size)}

/* ---------- member pages, server-rendered (src/members) ----------
   The old screens chose with buttons and React state; here a choice is a
   real radio input inside the chip or row, so it works without script and
   posts with the form. The look is the same: `:has(:checked)` is the old
   `--on`. */
.chip input,.row input{position:absolute;opacity:0;pointer-events:none}
.chip:has(input:checked){color:var(--text);border-color:var(--text)}
.chip:has(input:disabled){color:var(--faint);cursor:default;border-color:var(--hair)}
.chip:has(input:focus-visible),.row:has(input:focus-visible){outline:1px solid var(--dim);outline-offset:2px}
label.chip,label.row{cursor:pointer}
.qty{background:none;border:1px solid var(--hair);color:inherit;font:inherit;padding:.15em .4em;border-radius:2px}
.pie-pick{margin-top:.6rem}
.pie-pick__label{margin-bottom:.4rem}
.m-form{display:flex;flex-direction:column;align-items:center;gap:.6rem}
.m-form .field{border-bottom:1px solid var(--hair)}
.m-code{letter-spacing:.4em;font-variant-numeric:tabular-nums}
.m-orders{display:flex;flex-direction:column;align-items:center;gap:1.1rem}
.m-order{display:flex;flex-direction:column;align-items:center;gap:.15rem}
.m-link{word-break:break-all}
.m-rows{width:min(92vw,520px);text-align:left}
.m-rows .bill__row,.m-rows .tally__row{display:flex;justify-content:space-between;gap:1rem}
label.row,label.chip,.qty{text-transform:none;letter-spacing:inherit}
.m-claim{display:flex;flex-direction:column;align-items:center;gap:var(--gap);width:100%}
.m-link{text-transform:none;letter-spacing:.01em}
/* +/- stepper (claim): big enough to hit with a thumb, quiet until used. */
.stepper{grid-column:1 / -1;display:inline-flex;align-items:center;gap:.9rem;margin-top:.55rem}
.stepper__btn{width:34px;height:34px;display:inline-grid;place-items:center;border:1px solid var(--hair);border-radius:50%;background:none;color:var(--text);font-size:16px;line-height:1;cursor:pointer;transition:border-color .2s ease,opacity .2s ease;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.stepper__btn:hover:not(:disabled){border-color:var(--dim)}
.stepper__btn:active:not(:disabled){transform:scale(.94)}
.stepper__btn:disabled{opacity:.3;cursor:default}
.stepper__n{width:2.2ch;text-align:center;background:none;border:0;color:var(--dim);font:inherit;padding:0;-moz-appearance:textfield;appearance:textfield}
.stepper__n::-webkit-inner-spin-button,.stepper__n::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
.stepper--on .stepper__n{color:var(--text)}
.row--flat[data-pie]{cursor:default}
/* Pickup times: two rows that scroll sideways, edges fading out. */
.strip{display:grid;grid-auto-flow:column;grid-template-rows:repeat(2,auto);grid-auto-columns:max-content;gap:.5rem;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x proximity;scrollbar-width:none;padding:.25rem 1.2rem;width:min(92vw,520px);-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 1.2rem,#000 calc(100% - 1.2rem),transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 1.2rem,#000 calc(100% - 1.2rem),transparent 100%)}
.strip::-webkit-scrollbar{display:none}
.strip .chip{scroll-snap-align:start}
.strip__hint{font-size:11px;margin-top:.35rem}
/* A time we filled in for them (back to back), until they choose themselves. */
.chip--suggested:has(input:checked){border-style:dashed}
.row .stepper__n{position:static;opacity:1;pointer-events:auto}
.strip{grid-template-rows:auto}
.m-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:.4rem 1.6rem}
.stepper{justify-self:end}
/* Long lines (arrival directions, notes) keep a reading width, centred. */
.booked,.stack>.say,.stack .say{max-width:min(92vw,34rem);margin-left:auto;margin-right:auto}

/* The confirmation: receipt, getting there, then change of plans, all on
   one centred reading column. */
.m-done .booked{margin-top:0}
.m-change,.m-extra{display:flex;flex-direction:column;align-items:center;gap:.75rem;max-width:min(92vw,34rem);margin:0 auto}
.m-change .m-orders{gap:.85rem;margin-top:.2rem}
.m-change .m-actions{gap:.3rem 1.2rem}

/* ---------- profile ---------- */

.prof{gap:2.2rem;width:min(92vw,380px);margin-inline:auto}
.prof__head{display:flex;flex-direction:column;align-items:center;gap:.35rem}
.prof__photo{position:relative;width:76px;height:76px;border-radius:50%;border:0;padding:0;margin-bottom:.6rem;cursor:pointer;overflow:hidden;
  background:var(--hair);color:var(--dim);display:grid;place-items:center;font:inherit}
.prof__photo img{width:100%;height:100%;object-fit:cover;display:block}
.prof__photo i{position:absolute;inset:auto 0 0;padding:4px 0 6px;font-style:normal;font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:#fff;background:linear-gradient(transparent,rgba(0,0,0,.55));opacity:0;transition:opacity .25s ease}
.prof__photo:hover i,.prof__photo:focus-visible i,.prof__photo:not(.prof__photo--set) i{opacity:1}
.prof__photo:not(.prof__photo--set) i{color:var(--dim);background:none}
.prof__photo.busy{opacity:.5}
.prof__form{display:flex;flex-direction:column;gap:2.2rem;width:100%}
.prof__sec{display:flex;flex-direction:column;width:100%}
.prof__title{margin:0 0 .5rem;font-size:11px;letter-spacing:.14em;color:var(--dim)}
.line{display:grid;grid-template-columns:7.5em 1fr;align-items:baseline;gap:1em;border-top:1px solid var(--hair);padding:.7rem .1rem}
.prof__sec .line:last-child,.prof__sec .pref:last-of-type{border-bottom:1px solid var(--hair)}
.line__label{color:var(--dim);text-align:left}
.line__input{border:0;background:none;outline:none;padding:0;min-width:0;width:100%;text-align:right;text-transform:none;letter-spacing:.01em;font-size:13px;color:var(--text)}
@media (max-width:600px){.line__input{font-size:16px}}
.line__input::placeholder{color:var(--faint);text-transform:none}
.line:focus-within .line__label{color:var(--text)}
.pref{display:flex;justify-content:space-between;align-items:center;gap:1.2em;border-top:1px solid var(--hair);padding:.75rem .1rem;cursor:pointer;text-align:left}
.pref__text{display:flex;flex-direction:column;gap:.25rem}
.pref__hint{font-size:11px;color:var(--faint);text-transform:none;letter-spacing:.01em;line-height:1.4}
.pref__box{appearance:none;-webkit-appearance:none;flex:none;margin:0;width:30px;height:18px;border-radius:18px;background:var(--hair);position:relative;cursor:pointer;transition:background .25s ease}
.pref__box::after{content:'';position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--bg);transition:transform .25s cubic-bezier(.2,.8,.2,1)}
.pref__box:checked{background:var(--text)}
.pref__box:checked::after{transform:translateX(12px)}
.pref__box:focus-visible{outline:1px solid var(--text);outline-offset:3px}
.prof__note{margin:.7rem 0 0;font-size:11px;color:var(--faint);text-transform:none;text-align:left}
.prof__save{display:flex;justify-content:center}
.prof__foot{display:flex;justify-content:space-between;align-items:baseline;width:100%}
.prof__foot .m-form{margin:0}

/* ---------- menu ---------- */

/* The old menu list; each pie's photo, untouched, appears beside its row on
   hover and below it on a tap where there is no hover. Past drops fold
   away behind a click. */
.menu-page .pick{width:min(92vw,420px)}
.row--menu{position:relative;cursor:default}
.row--menu .row__desc{text-transform:none;letter-spacing:.01em;text-align:left;justify-self:start}
.row--pic{cursor:zoom-in}
.row__shot{position:absolute;left:calc(100% + 36px);top:50%;width:min(300px,calc((100vw - 420px) / 2 - 56px));
  transform:translateY(-50%) scale(.97);opacity:0;pointer-events:none;transition:opacity .3s ease,transform .45s cubic-bezier(.2,.8,.2,1);z-index:6}
.row__pic{display:block;width:100%;height:auto;box-shadow:0 14px 34px rgba(0,0,0,.22)}
.row__pic-note{display:block;margin-top:.5rem;font-size:10px;letter-spacing:.12em;color:var(--faint)}
.row--pic:hover .row__shot,.row--pic:focus-visible .row__shot{opacity:1;transform:translateY(-50%) scale(1)}
.row--menu:focus{outline:none}
.menu-archive{display:flex;flex-direction:column;align-items:center;width:100%}
.menu-archive summary{list-style:none;cursor:pointer;margin:0 auto}
.menu-archive summary::-webkit-details-marker{display:none}
.menu-archive[open] summary{margin-bottom:1rem}
.menu-archive .pick{margin:0 auto}
/* no room beside the list (phones, narrow windows) or no hover: the photo opens below the row on a tap */
@media (max-width:1000px),(hover:none){
  .row__shot{position:static;width:100%;grid-column:1 / -1;transform:none;opacity:1;display:none;margin-top:.8rem}
  .row--pic:focus .row__shot,.row--pic:focus-within .row__shot{display:block}
  .row--pic:hover .row__shot{transform:none}
}

/* the account rows sit in the same column as the rest of the profile */
.prof .m-rows{width:100%;padding:0 .1rem;box-sizing:border-box}
.prof .m-rows .bill__row{padding:.15rem 0}

/* menu descriptions sit flush left under the name, not centred like the page's other notes */
.menu-page .row--menu .row__desc.say{max-width:none;margin-left:0;margin-right:0;width:100%;text-align:left;justify-self:stretch}

/* Pickup times: the strip stays inside its column, centred, and never widens
   the page; each chip holds its own radio, so choosing a time never scrolls
   the page sideways to reach it. */
.slots.pie-pick{width:min(92vw,520px);align-items:center;margin-left:auto;margin-right:auto}
.slots.pie-pick .strip{width:100%;max-width:100%;box-sizing:border-box;margin:0 auto}
.strip .chip{position:relative}
.strip .chip input{inset:0;width:100%;height:100%;margin:0}
.m-claim{max-width:100%}
html,body{overflow-x:clip}
/* the claim list: descriptions flush left like the menu's */
.row--menu .row__desc.say{max-width:none;margin-left:0;margin-right:0;width:100%;text-align:left;justify-self:stretch}
.row--menu[data-pie]{cursor:default}
.row__left{color:var(--mark)}

/* ---------- the personal invite ---------- */

/* One column the width of a phone, centred on bigger screens: polaroids on
   top, the greeting large, then the way in. */
.inv{width:min(100%,420px);margin:0 auto;display:flex;flex-direction:column;gap:1.4rem;padding:4.5rem 0 3rem;text-align:left}
.inv__pols{position:relative;height:300px;margin:0 auto;width:min(100%,380px)}
.inv__pol{position:absolute;margin:0;background:#fbfaf6;padding:8px 8px 30px;box-sizing:border-box;
  box-shadow:0 2px 2px rgba(40,20,5,.16),4px 14px 22px rgba(40,20,5,.2)}
.inv__pol img{display:block;width:100%;object-fit:cover}
.inv__pol::before{content:"";position:absolute;left:50%;top:-12px;width:64px;height:22px;margin-left:-32px;background:rgba(236,226,196,.86)}
.inv__pol--1{left:2%;top:40px;width:39%;transform:rotate(-8deg)}.inv__pol--1 img{height:180px}.inv__pol--1::before{transform:rotate(4deg)}
.inv__pol--2{left:30%;top:0;width:42%;transform:rotate(3deg);z-index:2}.inv__pol--2 img{height:196px}.inv__pol--2::before{transform:rotate(-3deg)}
.inv__pol--3{left:59%;top:56px;width:38%;transform:rotate(9deg)}.inv__pol--3 img{height:176px}.inv__pol--3::before{transform:rotate(-6deg)}
.inv__hello{display:flex;flex-direction:column;gap:.55rem}
.inv__name{margin:0;font-size:44px;line-height:1;font-weight:400;letter-spacing:-.01em;text-transform:uppercase;color:var(--text)}
.inv__from{margin:0;font-size:22px;line-height:1.2;text-transform:none;letter-spacing:-.005em;color:var(--text)}
.inv__brand{margin:0;font-size:30px;line-height:1.05;letter-spacing:.01em;text-transform:uppercase;color:var(--text)}
.inv__say{margin:0;font-size:14px;line-height:1.55;text-transform:none;letter-spacing:.005em;color:var(--dim);max-width:34ch}
.inv__acts{display:flex;flex-direction:column;gap:.9rem;margin-top:.6rem}
.inv__cta{display:flex;justify-content:center;align-items:center;gap:.75em;height:54px;border:0;background:var(--text);color:var(--bg);
  font:inherit;font-size:13px;letter-spacing:.06em;text-transform:uppercase;text-decoration:none;cursor:pointer;width:100%}
.inv__cta .brk{color:var(--dim)}
.inv__cta:hover{opacity:.88}
.inv__more{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.inv__note{margin:0;font-size:11px;text-align:center;letter-spacing:.02em;text-transform:none;color:var(--dim)}

/* the guest menu: photos always showing */
.gmenu{width:min(100%,420px);margin:0 auto}
.gmenu__list{display:flex;flex-direction:column;width:100%;border-top:1px solid var(--hair)}
.gmenu__pie{display:flex;flex-direction:column;gap:.6rem;padding:1rem 0;border-bottom:1px solid var(--hair);text-align:left}
.gmenu__pic{display:block;width:100%;height:auto}
.gmenu__head{display:flex;justify-content:space-between;gap:1rem}
.gmenu__desc{margin:0;font-size:12px;line-height:1.45;text-transform:none;letter-spacing:.01em;color:var(--faint)}
.gmenu__acts{display:flex;flex-direction:column;gap:.7rem;width:100%}

/* joining: one step with an invite; a code or the waitlist without */
.join{width:min(100%,380px);margin:0 auto;align-items:stretch;text-align:left}
.join__title{margin:0;font-size:30px;line-height:1.05;letter-spacing:-.01em;text-transform:uppercase;color:var(--text)}
.join__form{display:flex;flex-direction:column;gap:1.1rem;width:100%;margin:0}
.join__field{display:flex;flex-direction:column;gap:.35rem;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
.join__field input{border:0;border-bottom:1px solid var(--hair);background:transparent;padding:.5rem 0;font:inherit;font-size:17px;text-transform:none;letter-spacing:0;color:var(--text);outline:none;border-radius:0}
.join__field input:focus{border-bottom-color:var(--text)}
.join__code{letter-spacing:.3em !important;text-transform:uppercase !important}
.join__or{display:flex;align-items:center;gap:.8rem;margin:.6rem 0 0;font-size:11px;letter-spacing:.06em;color:var(--faint)}
.join__or::before,.join__or::after{content:"";flex:1;height:1px;background:var(--hair)}
.join .act{align-self:center}

/* the invite, guest menu and join columns keep a side margin on phones */
.inv,.gmenu,.join{box-sizing:border-box;padding-left:max(22px,env(safe-area-inset-left,0px));padding-right:max(22px,env(safe-area-inset-right,0px))}
.gmenu,.join{width:min(100%,440px)}
.inv{width:min(100%,440px)}

/* the greeting as one short note: one size throughout, the details a quieter colour */
.inv__letter{margin:0;font-weight:400;font-size:30px;line-height:1.16;letter-spacing:-.005em;text-transform:none;color:var(--text)}
.inv__when{color:var(--dim)}

/* ---------- the invite, as a letter ---------- */
/* After a friend's note: centred, lowercase, one typewriter face, a pill for
   how many are left, one coloured line, signed in our own handwriting. */
@font-face{font-family:"2mp mono";src:url(/invite/mono.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}
.inv{text-align:center;align-items:center;gap:1.6rem;padding-top:4rem}
.inv__pols{height:236px;width:min(100%,320px)}
.inv__pol--1 img{height:140px}.inv__pol--2 img{height:156px}.inv__pol--3 img{height:136px}
.inv__pill{margin:0;font-family:"2mp mono","Courier New",ui-monospace,monospace;font-size:13px;text-transform:none;letter-spacing:0;color:var(--dim)}
.inv__pill b{display:inline-block;font-weight:400;color:var(--text);background:var(--hair);border-radius:100px;padding:.15em .7em;margin:0 .15em}
.inv__note{display:flex;flex-direction:column;gap:1.05rem;max-width:30ch;font-family:"2mp mono","Courier New",ui-monospace,monospace;font-size:15px;line-height:1.5;text-transform:none;letter-spacing:0;color:var(--text)}
.inv__note h1,.inv__note p{margin:0;font:inherit}
.inv__accent{color:var(--mark)}
.inv__sig{width:min(68%,260px);height:auto;margin-top:.4rem}
.inv__sig{filter:invert(.9)}
@media (prefers-color-scheme:light){:root:not([data-theme='dark']) .inv__sig{filter:none}}
:root[data-theme='light'] .inv__sig{filter:none}
.inv__acts{width:100%;align-items:stretch}
.inv .inv__cta{font-family:"2mp mono","Courier New",ui-monospace,monospace;text-transform:none;letter-spacing:.02em;font-size:15px;border-radius:2px}
.inv__more{justify-content:center;gap:.7em;font-family:"2mp mono","Courier New",ui-monospace,monospace;font-size:13px;text-transform:none;letter-spacing:0;color:var(--dim)}
.inv__more a{color:var(--dim);text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--hair)}
.inv__more a:hover{color:var(--text)}
.inv__fine{margin:0;font-family:"2mp mono","Courier New",ui-monospace,monospace;font-size:11px;text-transform:none;letter-spacing:0;color:var(--faint);text-align:center}

/* the line under Claim on the guest menu */
.gmenu__note{margin:0;font-size:12px;line-height:1.5;text-align:center;text-transform:none;letter-spacing:.01em;color:var(--dim)}
