/* Chai Pe Date — warm, small, and deliberately unromantic in its chrome.
   The product is low-stakes; the interface should not oversell it. */

:root {
  /* A card has to read as sitting ON the page, not as a slightly different
     shade of it. The old pair was four points of lightness apart. SPEC §7C.14 */
  --paper: #faf5ec;
  --card: #ffffff;
  --ink: #241c17;
  --ink-soft: #6b5b4e;
  --ink-faint: #9a8a7b;
  --line: #eadfd0;
  --amber: #c2521a;
  --amber-soft: #fbe8d8;
  --leaf: #2f6b4a;
  --leaf-soft: #e2f0e7;
  --warn: #8a5a08;
  --warn-soft: #fbeed8;
  --stop: #a33520;
  --stop-soft: #fbe2da;
  /* What goes ON --amber and --stop. In light they are deep enough for white;
     in dark they are lifted to stay visible against the paper, and white on a
     lifted amber is about 2:1 — legible on a desktop in a dark room and not
     much else. The ink comes back instead. */
  --on-accent: #ffffff;
  --radius: 14px;
  /* A comfortable line is 45–75 characters. At this size that lands around 72,
     and it is what the reading column narrows to on a phone — so the landing
     page and the app agree about how wide prose is allowed to get. */
  --measure: 34rem;
  --bar-h: 3.4rem;
  --shadow: 0 1px 2px rgba(36,28,23,.05), 0 8px 24px rgba(36,28,23,.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #14100d;
    --card: #1f1a15;
    --ink: #f0e6da;
    --ink-soft: #b6a695;
    --ink-faint: #8a7a6a;
    --line: #35291f;
    --amber: #e89250;
    --amber-soft: #35251a;
    --leaf: #7fc396;
    --leaf-soft: #1d2f23;
    --warn: #d6a55b;
    --warn-soft: #322717;
    --stop: #e08a75;
    --stop-soft: #33201b;
    --on-accent: #1a1209;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.25);
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.5 ui-rounded, "Segoe UI", system-ui, -apple-system, sans-serif;
  padding-bottom: 5rem;
  /* The page fills the window even when its content does not, so the footer
     below can sit at the bottom of the screen rather than wherever the
     content happened to stop. On a short page — an empty board, a table with
     two seats — it used to land in the middle with a third of a viewport of
     nothing under it, which reads as a page that failed to finish loading
     rather than as the end of one.

     dvh, with vh underneath it for anything that does not know dvh: on a
     phone browser vh is the tallest the viewport ever gets, so the footer
     would sit just below the fold until the address bar collapsed. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}
a { color: inherit; }

/* Both grow, so the column reaches the bottom of the window and the footer's
   auto margin has room to push into. .nav is fixed and out of flow, so making
   .shell a flex column does not move it. */
.shell { display: flex; flex-direction: column; flex: 1 0 auto; }
.wrap {
  max-width: var(--measure); margin: 0 auto; padding: 1.1rem 1rem 0;
  display: flex; flex-direction: column; flex: 1 0 auto; width: 100%;
}

/* The one piece of chrome that is not about using the product. Faint, at the
   end of the reading column, and never in the way. */
.legal {
  color: var(--ink-faint); font-size: .72rem; text-align: center;
  padding: 2rem 0 .5rem;
  /* What actually pins it: everything above takes its own height, and the
     leftover space of the column collects here. */
  margin-top: auto;
}
/* SPEC §7O.1.1. It belongs to the pages that are NOT the product — the
   landing and the four legal documents. Inside the app it was a second row of
   small links sitting on top of the nav bar, wrapping to two lines on a phone,
   under a board or a conversation it had nothing to do with. The account menu
   carries the same links there, which is what the app has always done. */
body.in-app .legal { display: none; }

/* --- the app bar (SPEC §7C.10–7C.12) ------------------------------------ */
/* Spans the window and stays put. The account is here rather than inside the
   reading column, where it crowded whatever the page was about. */
.topbar { position: sticky; top: 0; z-index: 30; }
.appbar {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; height: var(--bar-h); padding: 0 1.1rem;
  background: var(--card); border-bottom: 1px solid var(--line);
}
.mark {
  text-decoration: none; font-weight: 800; font-size: 1.05rem; letter-spacing: -.02em;
  display: inline-flex; align-items: center; gap: .4rem; color: var(--ink);
}
.mark span { color: var(--amber); }

/* the account: an avatar that opens a menu */
.who-btn {
  display: flex; align-items: center; gap: .45rem;
  background: none; border: 0; padding: .2rem; border-radius: 999px; cursor: pointer;
}
.who-btn:hover { background: var(--amber-soft); }
.menu {
  position: absolute; right: 1.1rem; top: calc(var(--bar-h) - .3rem); min-width: 14rem;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: .35rem; font-size: .9rem; z-index: 31;
}
.menu .head {
  padding: .5rem .6rem .55rem; border-bottom: 1px solid var(--line); margin-bottom: .3rem;
}
.menu .head b { display: block; }
.menu .head span { color: var(--ink-faint); font-size: .78rem; word-break: break-all; }
.menu a, .menu button {
  /* justify-content, because the base button rule centres its content and a
     menu row has to line its labels up with the ones above it */
  display: flex; align-items: center; justify-content: flex-start; gap: .6rem;
  width: 100%; text-align: left; font-weight: 400;
  padding: .5rem .6rem; border-radius: 8px; text-decoration: none;
  background: none; border: 0; font-size: inherit; color: inherit; cursor: pointer;
}
.menu a:hover, .menu button:hover { background: var(--amber-soft); }
/* SPEC §7P. Leaving is at the bottom, under Sign out, in the stop colour and
   not behind a submenu — Play checks that it is findable, and so does anybody
   annoyed enough to be looking for it. */
.menu button.leave { color: var(--stop); border-top: 1px solid var(--line);
  border-radius: 0 0 8px 8px; margin-top: .3rem; }
.menu button.leave:hover { background: var(--stop-soft); }

/* SPEC §7P. What goes and what stays, in the deletion sheet. Two lists rather
   than one with a mixed marker: the second is the reassuring half and reads as
   an afterthought if it is folded into the first. */
.goes, .stays { list-style: none; margin: .9rem 0 0; padding: 0; }
.goes { background: var(--stop-soft); border-radius: 10px; padding: .8rem .9rem; }
.stays { background: var(--leaf-soft); border-radius: 10px; padding: .8rem .9rem; }
.goes li, .stays li { position: relative; padding-left: 1.35rem; font-size: .88rem;
  line-height: 1.45; }
.goes li + li, .stays li + li { margin-top: .5rem; }
.goes li::before { content: "✕"; position: absolute; left: 0; color: var(--stop); font-weight: 700; }
.stays li::before { content: "✓"; position: absolute; left: 0; color: var(--leaf); font-weight: 700; }
.goes .faint, .stays .faint { display: block; }


/* the one-line promise, stated once */
.promise {
  font-size: .84rem; color: var(--ink-soft); border-left: 3px solid var(--amber);
  padding: .1rem 0 .1rem .7rem; margin: .25rem 0 1.1rem;
}

/* avatar */
.av {
  width: 1.9rem; height: 1.9rem; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-size: .8rem; font-weight: 700;
  background: var(--amber-soft); color: var(--amber);
}
.av.lg { width: 2.6rem; height: 2.6rem; font-size: 1rem; }
/* SPEC §7I.5 — a photo fills the same circle the initials did, so nothing
   around it moves when one becomes the other. */
img.av { object-fit: cover; background: var(--amber-soft); }
/* In the bar it is the only thing competing with the wordmark, so it is solid
   rather than a tint — a tinted circle on a white bar reads as disabled. */
.who-btn { position: relative; }
.who-btn .av { width: 2.1rem; height: 2.1rem; background: var(--amber); color: var(--on-accent); }

/* --- a photo of the tapri (SPEC §7K) ------------------------------------ */
/* A rectangle, not a circle. A face is a portrait and a stall is a scene, and
   cropping a shopfront to a circle throws away the half that tells you which
   corner you are looking for. */
.shot {
  width: 3.4rem; height: 2.6rem; border-radius: 8px; flex: none;
  object-fit: cover; background: var(--paper); border: 1px solid var(--line);
}
/* Full width where the job is recognising the place on arrival, rather than
   telling two rows apart. */
.shot.lg {
  width: 100%; height: auto; max-height: 15rem; margin-top: .6rem;
  border-radius: var(--radius);
}
/* §7K.11 — no photo means no element, never an empty frame. The class is for
   the picker's preview, which exists before anything is chosen: an <img> with
   no src re-requests the current page in some browsers, so it is hidden
   outright rather than left to render a broken icon. */
.shot.none { display: none; }

.shotpick { display: flex; flex-direction: column; align-items: flex-start; gap: .5rem; }
.shotpick .shot.lg { margin-top: 0; max-height: 11rem; width: auto; max-width: 100%; }
/* A file input cannot be styled, so the label is the button and the input is
   the part nobody sees. */
.filebtn {
  position: relative; display: inline-block; padding: .45rem .8rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--card); font-size: .85rem; font-weight: 600;
}
.filebtn:hover { background: var(--paper); }
.filebtn input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* --- the admin marker (SPEC §7C.16) ------------------------------------- */
/* On the avatar rather than beside the name, so it travels with the avatar and
   costs no width. Only ever on your own — never shown to ordinary members. */
.star {
  position: absolute; right: -1px; bottom: -1px; width: 1rem; height: 1rem;
  border-radius: 999px; background: var(--warn-soft); color: var(--warn);
  display: grid; place-items: center; font-size: .62rem; line-height: 1;
  box-shadow: 0 0 0 2px var(--card);
}

/* --- the admin console (SPEC §7C.15) ------------------------------------ */
/* Tabs wrap. They used to scroll sideways, which hid the last two off the
   right edge, and a tab nobody can see is a tab nobody uses. */
.tabrow { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1.1rem; }
.tabrow .chip { flex: none; }
.who-row { display: flex; align-items: center; gap: .7rem; }
.who-row > div { flex: 1; min-width: 0; }
.who-row .av { flex: none; }

/* cards */
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .9rem 1rem; margin-bottom: .75rem; box-shadow: var(--shadow);
  display: block; text-decoration: none; color: inherit;
}
.card.flat { box-shadow: none; }
/* SPEC §7C.3. A card that is yours says so in its edge as well as its tag, so
   the board can be scanned without reading it. */
.card.hosting { border-color: var(--amber); }
.card.mine { border-color: var(--leaf); }
.card h3 { margin: 0 0 .15rem; font-size: 1rem; letter-spacing: -.01em; }
.row { display: flex; align-items: center; gap: .5rem; }
.row.wrap-r { flex-wrap: wrap; }
.spread { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
.muted { color: var(--ink-soft); font-size: .85rem; }
.faint { color: var(--ink-faint); font-size: .78rem; }
.stack > * + * { margin-top: .5rem; }

/* slot card bits */
.when { font-variant-numeric: tabular-nums; font-weight: 700; }
.tag {
  display: inline-block; font-size: .72rem; padding: .12rem .5rem; border-radius: 999px;
  background: var(--amber-soft); color: var(--amber); font-weight: 600; white-space: nowrap;
}
.tag.grey { background: var(--line); color: var(--ink-soft); }
.tag.green { background: var(--leaf-soft); color: var(--leaf); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.stop { background: var(--stop-soft); color: var(--stop); }

.seats { display: flex; gap: .22rem; align-items: center; }
.seat { width: .55rem; height: .55rem; border-radius: 50%; background: var(--line); }
.seat.on { background: var(--amber); }

/* notes */
.note {
  border-radius: 10px; padding: .6rem .75rem; font-size: .86rem; line-height: 1.45;
  border: 1px solid var(--line); background: var(--paper);
}
.note.green { background: var(--leaf-soft); border-color: transparent; color: var(--leaf); }
.note.warn { background: var(--warn-soft); border-color: transparent; color: var(--warn); }
.note.stop { background: var(--stop-soft); border-color: transparent; color: var(--stop); }

/* The confirmation, said in passing. Its colour carries the outcome — green
   worked, red did not — so it can never be mistaken for the other. §7C.21 */
.toast {
  position: fixed; left: 1rem; right: 1rem; bottom: 5.5rem; z-index: 40;
  max-width: 32rem; margin: auto; box-shadow: var(--shadow); font-weight: 500;
}
@media (min-width: 880px) { .toast { bottom: 1.5rem; left: 15.5rem; } }

/* buttons */
button, .btn {
  font: inherit; font-weight: 650; cursor: pointer; text-decoration: none;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 10px; padding: .6rem .9rem; display: inline-flex;
  align-items: center; justify-content: center; gap: .4rem;
}
button.primary, .btn.primary { background: var(--amber); border-color: var(--amber); color: var(--on-accent); }
/* SPEC §7G.5.5 — an action that cannot be undone, or that takes something away
   from somebody, does not wear the same colour as the one that gives it. */
button.primary.stop, .btn.primary.stop { background: var(--stop); border-color: var(--stop); }
button.wide, .btn.wide { width: 100%; }
button.quiet { background: transparent; border-color: transparent; color: var(--ink-soft); padding: .4rem .2rem; }
button.small { font-size: .85rem; padding: .42rem .7rem; }
button[disabled] { opacity: .45; cursor: not-allowed; }
/* A control that reads as a link because it continues a sentence, but is a
   button because it opens the picker rather than going anywhere. */
button.linky {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--amber); text-decoration: underline; cursor: pointer;
}
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
form.inline { display: inline; }

/* forms */
label { display: block; font-size: .82rem; font-weight: 650; margin: 0 0 .3rem; }
label .hint { display: block; font-weight: 400; color: var(--ink-faint); font-size: .76rem; margin-top: .1rem; }
/* Every text-ish input, rather than a list of types that has to be extended
   each time a form gains a field — which is how the profile link (SPEC §7G.2)
   arrived unstyled and half a column wide. Checkboxes and radios are hidden by
   .choices and are excluded here so they stay that way. */
input:not([type=checkbox]):not([type=radio]), select, textarea {
  font: inherit; width: 100%; padding: .55rem .65rem; border-radius: 10px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
}
textarea { resize: vertical; min-height: 4rem; }
/* min-inline-size is the one that is not tidying up.
   A fieldset is the only element the UA stylesheet gives
   `min-inline-size: min-content`, so it refuses to shrink below its widest
   unbreakable content — and #daychips is a nowrap flex row eight days long.
   Its `overflow-x: auto` never got to act, because the fieldset grew instead
   of constraining it: 649px inside a 412px phone, which made the whole of
   /open scroll sideways and stretched the fixed nav to match. */
fieldset { border: 0; padding: 0; margin: 0 0 1rem; min-inline-size: 0; }
/* SPEC §7G.2 — the three look-you-up boxes share one fieldset: one heading,
   three named inputs, and each box's refusal directly under the box it is
   about (§7G.2.2). The error div is always present and usually empty, so a
   message appearing does not reflow the boxes around it more than it must. */
.sublabel { font-weight: 550; font-size: .78rem; margin: .55rem 0 .25rem; color: var(--ink-faint); }
.fielderr { color: var(--stop); font-size: .76rem; min-height: 0; margin: .15rem 0 0; }
.fielderr:empty { margin: 0; }
.choices { display: flex; gap: .4rem; flex-wrap: wrap; }
.choices input { position: absolute; opacity: 0; pointer-events: none; }
.choices label {
  margin: 0; padding: .42rem .7rem; border-radius: 999px; border: 1px solid var(--line);
  background: var(--card); cursor: pointer; font-weight: 550; font-size: .85rem;
}
.choices input:checked + label { background: var(--amber); border-color: var(--amber); color: var(--on-accent); }
/* A duration that cannot fit the chosen start is struck through, not merely
   dimmed: dimmed reads as "not selected", struck reads as "not available".
   SPEC §7F.3 */
.choices input:disabled + label {
  opacity: .45; cursor: not-allowed; text-decoration: line-through;
}

/* --- opening a table (SPEC §7F) ----------------------------------------- */
/* What the current choice means, said at the field rather than after the
   button. Green when it clears the rules, red when it does not. */
.fitline {
  display: flex; align-items: flex-start; gap: .45rem;
  margin: .45rem 0 0; font-size: .85rem; line-height: 1.4;
}
.fitline:empty { margin: 0; }
.fitline.ok { color: var(--leaf); }
.fitline.no { color: var(--stop); }
.whytag { color: var(--ink-faint); font-size: .8rem; }

/* the recap inside the confirmation sheet */
.recap {
  text-align: left; background: var(--paper); border-radius: 12px;
  padding: .8rem .9rem; margin: 1rem auto; max-width: 26rem;
}
.recap div { font-size: .88rem; color: var(--ink-soft); }
.recap div + div { margin-top: .2rem; }
.recap b { color: var(--ink); }

/* nav */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; background: var(--card);
  border-top: 1px solid var(--line); display: flex; padding: .4rem .5rem calc(.4rem + env(safe-area-inset-bottom));
}
.nav a {
  flex: 1; text-align: center; text-decoration: none; color: var(--ink-faint);
  font-size: .7rem; padding: .3rem 0; display: grid; gap: .1rem; justify-items: center;
}
.nav a.on { color: var(--amber); }
.nav .ic { font-size: 1.15rem; line-height: 1; }
.dot { width: .4rem; height: .4rem; border-radius: 50%; background: var(--stop); position: absolute; margin: -.2rem 0 0 1rem; }

h2 { font-size: .8rem; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-faint); margin: 1.5rem 0 .6rem; }
hr { border: 0; border-top: 1px solid var(--line); margin: 1.25rem 0; }
.empty { text-align: center; color: var(--ink-faint); padding: 2rem 1rem; font-size: .9rem; }

/* horizontal filter row — chips never wrap their own text */
.scroller {
  flex-wrap: nowrap; overflow-x: auto; margin: .6rem 0 1.1rem;
  padding-bottom: .3rem; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.scroller::-webkit-scrollbar { display: none; }
.chip {
  flex: none; white-space: nowrap; text-decoration: none;
  padding: .4rem .75rem; border-radius: 999px; border: 1px solid var(--line);
  background: var(--card); font-size: .85rem; font-weight: 600; color: var(--ink-soft);
}
.chip.on { background: var(--amber); border-color: var(--amber); color: var(--on-accent); }

/* --- the table thread --------------------------------------------------- */
.tl-note {
  display: flex; align-items: center; gap: .6rem; margin: .6rem 0;
  color: var(--ink-faint); font-size: .76rem;
}
.tl-note::before, .tl-note::after { content: ""; flex: 1; height: 1px; background: var(--line); }

.msg { margin: .55rem 0; max-width: 88%; }
.msg.mine { margin-left: auto; text-align: right; }
.msg-head { font-size: .74rem; color: var(--ink-soft); margin-bottom: .18rem; }
.msg-head .faint { margin-left: .35rem; }
.bubble {
  display: inline-block; text-align: left; padding: .45rem .7rem;
  border-radius: 12px 12px 12px 3px; background: var(--paper);
  border: 1px solid var(--line); font-size: .9rem; line-height: 1.4;
  overflow-wrap: anywhere;
}
.msg.mine .bubble {
  border-radius: 12px 12px 3px 12px; background: var(--amber-soft);
  border-color: transparent; color: var(--amber);
}
button.tiny {
  font-size: .68rem; padding: .1rem .35rem; border-radius: 6px; font-weight: 500;
  background: transparent; border-color: transparent; color: var(--ink-faint);
}
button.tiny:hover { color: var(--stop); }

.compose { display: flex; gap: .45rem; margin-top: .8rem; }
.compose input { flex: 1; }
.compose button { flex: none; }

/* --- client-only additions ---------------------------------------------- */
.step-up {
  background: var(--amber-soft); border: 1px solid transparent; color: var(--amber);
  border-radius: var(--radius); padding: .85rem 1rem; margin: .75rem 0;
}
.step-up b { display: block; margin-bottom: .35rem; }
.step-up .btns { margin-top: .7rem; }

.dev-banner {
  background: var(--warn-soft); color: var(--warn); text-align: center;
  font-size: .74rem; padding: .3rem .5rem; font-weight: 600;
}

.sheet {
  position: fixed; inset: 0; background: rgba(20,14,10,.45);
  display: grid; place-items: end center; z-index: 20;
}
.sheet-body {
  background: var(--card); width: 100%; max-width: 34rem;
  border-radius: var(--radius) var(--radius) 0 0; padding: 1.1rem 1rem 2rem;
  max-height: 85vh; overflow-y: auto;
}
.sheet h3 { margin: 0 0 .2rem; }

.people-pick { display: grid; gap: .5rem; }
.people-pick button { width: 100%; text-align: left; justify-content: flex-start; }

.spinner { text-align: center; color: var(--ink-faint); padding: 3rem 1rem; font-size: .9rem; }
.level-pill {
  font-size: .68rem; font-weight: 700; padding: .1rem .4rem; border-radius: 5px;
  background: var(--line); color: var(--ink-soft); margin-left: .3rem;
}

/* --- the web view (SPEC §7D) -------------------------------------------- */
/* Below 880px none of this exists: the phone view is the markup above, in one
   column. These rules only shape the separate markup the web view renders. */
@media (min-width: 880px) {
  /* The reading column stays readable; the window is filled by putting
     something real beside it, not by stretching a line of text. §7D.2 */
  .wrap { max-width: 78rem; padding: 1.3rem 1.4rem 0; }

  .webgrid {
    display: grid; grid-template-columns: minmax(0, 1fr) 20rem;
    gap: 1.8rem; align-items: start;
  }
  /* A phone scrolls its filters sideways because it has to. A window does not,
     and a chip past the right edge is a filter nobody knows exists. */
  .webgrid .scroller { flex-wrap: wrap; overflow-x: visible; }
  .side { position: sticky; top: calc(var(--top-h, 3.4rem) + 1.3rem); display: grid; gap: 1rem; }
  .side h2 { margin: 0 0 .5rem; }
  .side .card { margin: 0; }

  /* §7D.3 — a table and its conversation, side by side. */
  .twopane {
    display: grid; grid-template-columns: minmax(0, 1fr) 24rem;
    gap: 1.8rem; align-items: start;
  }
  .twopane .pane { position: sticky; top: calc(var(--top-h, 3.4rem) + 1.3rem); }
  .twopane .pane h2:first-child { margin-top: 0; }
  /* "wide" means "as wide as a thumb needs". Beside a mouse, a button spanning
     a 900px column reads as a mistake rather than as emphasis. */
  .twopane button.wide, .twopane .btn.wide { width: auto; min-width: 13rem; }
}

/* --- navigation: a bar under a thumb, a rail beside a mouse -------------- */
/* SPEC §7C.1. Same markup; only this block differs. */
@media (min-width: 880px) {
  /* The inset belongs to the board, not to the page: the bar spans the
     window, and padding on <body> pushed it off the rail. SPEC §7C.10 */
  body { padding-bottom: 0; }
  .shell { padding-left: 14rem; }
  .nav {
    /* Clears the whole sticky block, not just the bar: in development a
       banner sits above it and wraps at some widths. SPEC §7C.10 */
    top: var(--top-h, 3.4rem); right: auto; bottom: 0; width: 14rem;
    flex-direction: column; align-items: stretch; gap: .15rem;
    border-top: 0; border-right: 1px solid var(--line);
    padding: 1rem .6rem;
  }
  /* The base rule makes each link a centred grid, which stacks icon over
     label. A rail wants them side by side, so switch the box model too. */
  .nav a {
    display: flex; flex: none; flex-direction: row;
    align-items: center; justify-content: flex-start;
    gap: .7rem; padding: .55rem .8rem; border-radius: 10px; font-size: .92rem;
  }
  .nav a.on { background: var(--amber-soft); font-weight: 600; }
  .nav .ic { font-size: 1.1rem; }
  .nav .dot { margin: -.5rem 0 0 .9rem; }
}

/* --- a journey that ended (SPEC §7C.20) --------------------------------- */
.done { text-align: center; padding: 2.4rem 0 1rem; }
.done .seal {
  width: 3.6rem; height: 3.6rem; border-radius: 999px; margin: 0 auto 1.1rem;
  display: grid; place-items: center; font-size: 1.6rem;
  background: var(--leaf-soft); color: var(--leaf);
}
.done .seal.stop { background: var(--stop-soft); color: var(--stop); }
.done h1 { font-size: 1.6rem; letter-spacing: -.02em; margin: 0 0 .5rem; line-height: 1.15; }
.done .lede { color: var(--ink-soft); margin: 0 auto 1.6rem; max-width: 26rem; }
.done .steps {
  text-align: left; max-width: 26rem; margin: 0 auto 1.6rem; display: grid; gap: .8rem;
}
.done .steps > div { display: flex; gap: .7rem; align-items: flex-start; font-size: .9rem; }
.done .steps > div > div { color: var(--ink-soft); }
.done .steps b { display: block; color: var(--ink); }
.done .steps span.ic { font-size: 1.1rem; line-height: 1.3; flex: none; }

/* --- the landing page ---------------------------------------------------- */
/* The wrap widens to 78rem at desktop for the board, which is two columns of
   cards. The landing page is one column of prose, and inheriting that width
   ran its paragraphs to about 160 characters — twice a readable line, where
   the eye loses its place coming back to the left edge. It keeps the measure
   instead, at every width. */
.landing { padding: 1.4rem 0 1rem; max-width: var(--measure); margin: 0 auto; }
.landing h1 {
  font-size: 2rem; letter-spacing: -.03em; margin: 0 0 .4rem; line-height: 1.15;
}
/* The first screen is the name in the bar, this, and the button. The
   photograph is the argument — two glasses on a bench is the product with
   nothing explained — so it gets the room a headline used to take. */
.landing .hero { margin: 0 0 1.4rem; }
.landing .hero img {
  display: block; width: 100%; height: min(58vh, 26rem); object-fit: cover;
  border-radius: var(--radius); background: var(--card);
}
/* The one line the page is allowed. Under the photograph rather than over it:
   the picture makes the claim, this names it. */
.landing .tagline {
  font-size: 1.3rem; letter-spacing: -.02em; color: var(--ink);
  margin: 1.1rem 0 .3rem;
}
/* The safety shape in one line, since the three rules that carried it are
   gone. Both halves are rules the product actually enforces: a group table
   dissolves rather than run with two (§5.7), and nothing runs after dark. */
.landing .tagsub { color: var(--ink-soft); margin: 0 0 1.4rem; }
.landing .lede { font-size: 1.05rem; color: var(--ink-soft); margin: 0 0 1.6rem; }
.landing .points { display: grid; gap: .95rem; margin: 1.6rem 0; }
/* Direct children only: the inner div holds the text and must not become a
   flex row itself, which turned every label into a one-word column. */
.landing .points > div { display: flex; gap: .7rem; align-items: flex-start; font-size: .92rem; }
.landing .points > div > div { flex: 1; color: var(--ink-soft); }
.landing .points b { display: block; color: var(--ink); margin-bottom: .1rem; }
.landing .points span.ic { font-size: 1.15rem; line-height: 1.35; flex: none; }
/* The last thing on the page, and the only thing under the button: one rule,
   one note. It used to sit inside a section wrapper that drew a border of its
   own, so an emptied page showed two rules with a gap of nothing between. */
.landing .after {
  margin-top: 2.5rem; padding-top: 1.2rem; border-top: 1px solid var(--line);
  font-size: .85rem; color: var(--ink-faint);
}
.landing .after a { color: var(--ink-soft); }

/* Logged out there is no rail and no bar, so the page should not leave room. */
/* Signed out there is nowhere to navigate to, so the rail is not merely empty
   — it is gone. An empty one left a white gutter down the side of the landing
   page, which the lifted palette made obvious. */
body.no-nav .nav { display: none; }
body.no-nav { padding-bottom: 1rem; }
@media (min-width: 880px) { body.no-nav .shell { padding-left: 0; } }

/* --- the area picker (SPEC §7C.5–7C.9) ---------------------------------- */
.area-bar {
  display: flex; align-items: center; gap: .5rem; width: 100%;
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: .6rem .75rem; margin: .1rem 0 .85rem; box-shadow: var(--shadow);
  font: inherit; cursor: pointer; text-align: left;
}
.area-bar .pin { font-size: 1.05rem; }
.area-bar b { font-size: 1rem; letter-spacing: -.01em; }
.area-bar .sub { display: block; color: var(--ink-faint); font-size: .76rem; margin-top: .05rem; }
.area-bar .caret { margin-left: auto; color: var(--ink-faint); font-size: .8rem; }

.area-row {
  display: flex; gap: .7rem; align-items: flex-start; width: 100%;
  padding: .7rem .6rem; border: 0; border-radius: 10px;
  background: transparent; font: inherit; cursor: pointer; text-align: left;
}
.area-row:hover { background: var(--paper); }
.area-row.current { background: var(--amber-soft); }
.area-row .tick { width: 1.1rem; color: var(--amber); font-weight: 700; flex: none; }
.area-row .body { flex: 1; }
.area-row b { display: block; }
.area-row .why { display: block; color: var(--ink-faint); font-size: .78rem; margin-top: .1rem; }
.meter { display: block; height: .3rem; border-radius: 999px; background: var(--line); overflow: hidden; margin-top: .4rem; }
.meter > i { display: block; height: 100%; background: var(--warn); }
.meter.live > i { background: var(--leaf); }

/* SPEC §7M.9. The dashboard. Totals across the top because somebody will ask
   for them out loud, and small — the two gap cards under them are what an
   operator is meant to act on, so they must not be the quiet part of the page. */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: .5rem; margin: 0 0 1rem;
}
.tile {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .7rem .8rem; text-align: center;
}
.tile b { display: block; font-size: 1.35rem; letter-spacing: -.02em; }
.tile span { font-size: .72rem; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; }

/* Wide content scrolls inside its own box. A table of eight columns on a phone
   must not make the whole page slide sideways. */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.grid { border-collapse: collapse; width: 100%; font-size: .85rem; }
.grid th, .grid td {
  text-align: right; padding: .4rem .55rem; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.grid th:first-child, .grid td:first-child { text-align: left; }
.grid th {
  font-weight: 600; font-size: .7rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-faint);
}

/* SPEC §7O. The privacy statement and the terms are separate documents with no
   script behind them, so they get prose styling the app itself never needs. */
.doc { padding: 1.4rem 0 2rem; max-width: var(--measure); margin: 0 auto; }
.doc h1 { font-size: 1.6rem; letter-spacing: -.02em; margin: .2rem 0 .6rem; }
.doc h2 {
  font-size: 1rem; text-transform: none; letter-spacing: 0; color: var(--ink);
  margin: 1.8rem 0 .4rem;
}
.doc p, .doc li { color: var(--ink-soft); font-size: .95rem; }
.doc .lede { font-size: 1.02rem; color: var(--ink-soft); }
.doc ul { padding-left: 1.1rem; }
.doc li { margin: .35rem 0; }
.doc b { color: var(--ink); }
.crumb { font-size: .8rem; color: var(--ink-faint); margin: 0 0 1rem; }

.gapcard { background: var(--amber-soft); border-color: transparent; }
.gapcard b { color: var(--amber); }

/* the picker sheet */
.sheet-search { position: relative; margin: .2rem 0 .9rem; }
.sheet-search input {
  padding-left: 2.1rem; font-size: .95rem; border-radius: 10px;
}
.sheet-search .mag {
  position: absolute; left: .7rem; top: 50%; transform: translateY(-50%);
  color: var(--ink-faint); font-size: .9rem; pointer-events: none;
}
.sheet-group {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-faint); margin: .9rem 0 .2rem .6rem;
}
.sheet-group:first-of-type { margin-top: .3rem; }
.area-row .hit { background: var(--amber-soft); border-radius: 3px; }
.area-row[disabled] { opacity: 1; cursor: default; }
.area-row .near { display: block; color: var(--ink-faint); font-size: .74rem; margin-top: .15rem; }
.sheet-none { text-align: center; padding: 1.4rem .5rem .4rem; }
.sheet-none b { display: block; margin-bottom: .3rem; }

/* SPEC §7G.3 — the profile link on a person at your table. Quiet: it is a way
   to check somebody, not a call to action, and it must not compete with the
   buttons that actually do something. */
.proflink {
  display: inline-block;
  margin-top: .25rem;
  font-size: .8rem;
  font-weight: 600;
  color: var(--amber);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.proflink:hover { border-bottom-color: currentColor; }

/* SPEC §7G.5 — admin forms in a sheet. A sheet is short, so the fields sit
   tighter than they do on a full page, and the hints stay because the hints
   are the reason these are forms and not prompts. */
.adminform fieldset { margin-bottom: .75rem; }
.adminform .hint { margin-top: .05rem; }
.checks { display: flex; flex-direction: column; gap: .5rem; }
.check { display: flex; gap: .55rem; align-items: flex-start; font-weight: 400; }
.check input[type=checkbox] {
  width: 1.05rem; height: 1.05rem; margin: .15rem 0 0; flex: none;
  accent-color: var(--amber);
}
.check > span { font-size: .82rem; font-weight: 650; }

/* SPEC §7G.4 — Open in Maps, wherever a tapri's address is shown. Quiet, like
   the profile link: it answers "how do I find this", and it is not the thing
   anybody came to the page to press. */
.maplink {
  display: inline-block;
  margin-top: .3rem;
  font-size: .8rem;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.maplink:hover { color: var(--amber); border-bottom-color: currentColor; }
.pair { display: flex; gap: .5rem; }

/* SPEC §7F.9 — the day strip reuses .scroller, which already handles the
   sideways overflow. It only needs the filter row's margins taken back off,
   because this one lives inside a fieldset that supplies its own. */
.choices.scroller { margin: 0; }
.choices.scroller label { white-space: nowrap; }

/* SPEC §7C.23.3 — the profile card on My plans. */
.card .editlink { display: inline-block; margin-top: .7rem; font-size: .85rem; color: var(--ink-soft); text-decoration: none; }
.card .editlink:hover { color: var(--amber); }
