/* Paca. Phone first, 390px design target, 44px minimum tap targets.
 *
 * Two self-hosted fonts and nothing else fetched from anywhere: CLAUDE.md
 * forbids CDN fonts, so both files live in public/ beside this stylesheet.
 * Licences travel with them in FONT-LICENSES.md.
 *
 * Both are VARIABLE fonts with a 400-700 weight axis, which is why each
 * family is declared once with `font-weight: 400 700` rather than once per
 * weight. Declaring a single weight instead would make the browser
 * synthesise bold by smearing the outlines. */

@font-face {
  font-family: "Bitter";
  src: url("bitter.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3";
  src: url("source-sans-3.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* The palette is SAMPLED FROM THE ARTWORK, not picked to sit near it:
   --pine and --bone are the two actual pixel values in the alpaca mark. The
   greys are biased green rather than neutral so nothing on screen looks like
   it arrived from a different kit.

   Green is used sparingly and structurally — the header bar, the primary
   action, a checked box. List bodies stay on warm paper: gear lists are long,
   and a screen that is mostly dark green gets tiring before the bottom. */
:root {
  --tap: 44px;
  --pad: 16px;

  --pine: #244938;      /* primary: header bars, primary buttons */
  --pine-deep: #162C22; /* deep surfaces */
  --bone: #EEE6D6;      /* the mark; text on pine */
  --paper: #F7F4ED;     /* page ground */
  --card: #FFFFFF;      /* raised surfaces */
  --sunk: #EFEDE4;      /* quiet fills */
  --ink: #1B241E;       /* body text — near-black, green-biased */
  --moss: #5E6B60;      /* secondary text */
  --faint: #939C93;     /* tertiary text, empty checkbox borders */
  --rule: #E1E4DA;      /* hairlines */
  --ember: #9A3B1F;     /* destructive only */

  --display: "Bitter", Georgia, "Times New Roman", serif;
  --text: "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI",
          Roboto, sans-serif;

  /* The header bar's exact height. .tabs sticks directly beneath it, so the
     two numbers have to agree — keep them together rather than leaving a
     magic number further down the file. */
  --bar-h: 76px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 17px/1.45 var(--text);
  color: var(--ink);
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}

/* The app is a phone-width column, and on a desktop browser it stays one
   rather than stretching a 390px design across 1400px. Before this, every
   screen — the sign-in page most visibly — was pinned hard to the left edge
   of a wide window. One wrapper fixes all of them at once. */
#app {
  max-width: 430px;
  margin: 0 auto;
  min-height: 100vh;
  background: var(--paper);
}

@media (min-width: 520px) {
  body { background: var(--sunk); }
  #app {
    border-left: 1px solid var(--rule);
    border-right: 1px solid var(--rule);
    box-shadow: 0 1px 2px rgba(22, 44, 34, 0.05), 0 12px 28px rgba(22, 44, 34, 0.07);
  }
}

button {
  font: inherit;
  font-family: var(--text);
  font-weight: 600;
  font-size: 16.5px;
  min-height: var(--tap);
  border-radius: 10px;
  border: 1px solid var(--rule);
  background: var(--card);
  color: var(--ink);
  padding: 11px 16px;
  cursor: pointer;
}

input, select {
  font: inherit;
  font-family: var(--text);
  min-height: var(--tap);
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--card);
  color: var(--ink);
}
input::placeholder { color: var(--faint); }

/* ---------- header bar ---------- */

.bar {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--bar-h);
  padding: 14px var(--pad);
  position: sticky;
  top: 0;
  background: var(--pine);
  color: var(--bone);
  z-index: 5;
}
.bar h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0;
  flex: 1;
  min-width: 0;
}
/* The mark, not the launcher icon. An icon is a rounded tile made for a
   home screen; dropping one inside the interface reads as printing a book's
   cover on page one. This is the silhouette alone, beside the wordmark. */
.bar .mk { width: 26px; height: 26px; flex: none; display: block; }
/* Bar buttons sit on pine, so they cannot use the card-coloured default. */
.bar button {
  background: transparent;
  color: var(--bone);
  border-color: rgba(238, 230, 214, 0.4);
  font-size: 15.5px;
  padding: 10px 14px;
}

.pad { padding: var(--pad); }

/* ---------- notices ---------- */

.banner {
  background: var(--sunk);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--pine);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 0 0 var(--pad);
}

.empty { color: var(--moss); }

.lead { font-size: 18px; margin: 0 0 var(--pad); }

#clerk-signin { margin: var(--pad) 0; }

/* ---------- the lists screen ---------- */

.cards { list-style: none; margin: 0 0 var(--pad); padding: 0; }
.cards li { margin-bottom: 8px; }
.card {
  width: 100%;
  text-align: left;
  min-height: 64px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 13px 14px;
}
/* List names are set in the display face, the same as the list's own title
   in the header bar it opens into. */
.card-name {
  font-family: var(--display);
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.card-sub {
  font-size: 13.5px;
  font-weight: 400;
  color: var(--moss);
  font-variant-numeric: tabular-nums;
}

button.primary {
  background: var(--pine);
  border-color: var(--pine);
  color: var(--bone);
  font-weight: 600;
}
button.big { width: 100%; min-height: 48px; font-size: 17px; }
/* Destructive actions are the only place --ember appears. */
button.danger { color: var(--ember); border-color: var(--ember); background: transparent; }

#toast {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: 12px;
  max-width: 406px;
  margin: 0 auto;
  background: var(--pine-deep);
  color: var(--bone);
  padding: 14px 16px;
  border-radius: 10px;
  font-size: 16px;
  z-index: 50;
  pointer-events: none;
}
#toast[hidden] { display: none; }

/* ---------- the wizard ---------- */

.question {
  font-family: var(--display);
  font-weight: 600;
  font-size: 23px;
  line-height: 1.2;
  letter-spacing: -0.012em;
  margin: 0 0 var(--pad);
}
.choices { display: flex; flex-direction: column; gap: 10px; }
.choice { min-height: 56px; font-size: 17px; font-weight: 400; text-align: left; }
.choice.chosen {
  border-color: var(--pine);
  border-width: 2px;
  color: var(--pine);
  font-weight: 700;
}
.hint { color: var(--moss); font-size: 14.5px; margin: 8px 0 var(--pad); }

/* ---------- a list, building mode ---------- */

.section { margin-top: 26px; }
/* Title, weight and the section tools share one head block, with a single
   hairline under the lot. The mockup rules only under the title, but it has
   no tools row — ours has four buttons that must not float unattached. */
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2px 10px;
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--rule);
}
.section-head h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 16.5px;
  letter-spacing: -0.005em;
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
.section-tools { display: flex; flex-wrap: wrap; gap: 6px; flex: 1 0 100%; margin-top: 10px; }
.section-tools button { min-width: var(--tap); padding: 8px 12px; font-size: 15px; font-weight: 400; }
.section-tools button[disabled] { opacity: 0.35; }

/* Items are grouped into one raised card with hairlines between rows, rather
   than 300 separate bordered boxes down a long list. */
.items {
  list-style: none;
  margin: 10px 0;
  padding: 0;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  overflow: hidden;
}
.items li { margin: 0; }
.items li + li .item, .items li + li .pack-row { border-top: 1px solid var(--rule); }
.item {
  width: 100%;
  text-align: left;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-height: var(--tap);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 10px 14px;
}
.item-main { display: flex; gap: 8px; align-items: baseline; }
.item-name { font-size: 16px; font-weight: 400; }
.qty { color: var(--moss); font-weight: 400; font-variant-numeric: tabular-nums; }
.item-note { font-size: 13.5px; font-weight: 400; color: var(--moss); }
.item-name, .item-note { overflow-wrap: anywhere; }

.add-gear {
  width: 100%;
  margin-top: 4px;
  background: transparent;
  border-style: dashed;
  border-color: var(--faint);
  color: var(--pine);
}
.list-tools { display: flex; flex-direction: column; gap: 10px; margin: 28px 0 40px; }
/* "+ Add a section" follows the last section's dashed Add Gear button, and
   without this the two sit 4px apart and read as one control. */
.section + button.big { margin-top: 18px; }

/* ---------- the Add Gear sheet ---------- */

#sheet-backdrop {
  position: fixed; inset: 0; background: rgba(22, 44, 34, 0.45); z-index: 20;
}
#sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  max-width: 430px;
  margin: 0 auto;
  max-height: 92vh; overflow-y: auto;
  background: var(--paper);
  border-radius: 16px 16px 0 0;
  z-index: 30;
  box-shadow: 0 -4px 24px rgba(22, 44, 34, 0.22);
  padding-bottom: env(safe-area-inset-bottom);
}
#sheet-backdrop[hidden], #sheet[hidden] { display: none; }
.sheet-inner { padding: var(--pad); }
.sheet-inner h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.01em;
  margin: 0 0 12px;
}
.sheet-inner label {
  display: block; font-weight: 600; margin: 14px 0 6px; font-size: 15px;
  color: var(--moss);
  letter-spacing: 0.02em;
}

.stepper { display: flex; align-items: center; gap: 12px; }
.stepper button { width: 56px; min-height: 52px; font-size: 24px; }
.stepper output {
  font-size: 22px; min-width: 48px; text-align: center;
  font-variant-numeric: tabular-nums;
}

.weight-row { display: flex; gap: 10px; }
.weight-row input { flex: 1; }
.weight-row select { width: 96px; }

.toggle { display: flex; align-items: center; gap: 12px; min-height: var(--tap); }
.toggle input { width: 28px; height: 28px; min-height: 0; margin: 0; flex: none; accent-color: var(--pine); }
.toggle span { font-weight: 400; color: var(--ink); font-size: 16px; }

.sheet-buttons { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; }

/* ---------- Building / Packing ---------- */

.tabs {
  display: flex;
  gap: 8px;
  padding: 12px var(--pad);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: var(--bar-h); /* sits directly under the sticky .bar */
  background: var(--paper);
  z-index: 4;  /* below .bar's 5, above content */
}
.tab { flex: 1; min-height: 52px; font-size: 17px; }
/* Words, not icons, and the active one is unmistakable. */
.tab.on {
  background: var(--pine);
  border-color: var(--pine);
  color: var(--bone);
  font-weight: 700;
}

.pack-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 12px 14px;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 0;
  font-weight: 400;
}

/* The checkbox is drawn in CSS: no icon font, no SVG file, nothing fetched. */
.box {
  position: relative;
  flex: none;
  width: 26px;
  height: 26px;
  border: 2px solid var(--faint);
  border-radius: 6px;
  background: var(--card);
}
.pack-row.packed .box {
  background: var(--pine);
  border-color: var(--pine);
}
.pack-row.packed .box::after {
  content: "";
  position: absolute;
  left: 8px;
  top: 2px;
  width: 7px;
  height: 14px;
  border: solid var(--bone);
  border-width: 0 3px 3px 0;
  transform: rotate(45deg);
}

.pack-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Checked rows stay exactly where they are — nothing sorts or moves. */
.pack-row.packed .item-name { text-decoration: line-through; color: var(--moss); }

.progress { margin: 0; color: var(--moss); font-size: 13.5px; font-variant-numeric: tabular-nums; }

/* ---------- weights ---------- */

.totals {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 14px;
  margin-bottom: var(--pad);
}
.total-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 3px 0;
  font-size: 17px;
}
.total-row strong { font-weight: 700; font-variant-numeric: tabular-nums; }
.not-weighed { margin: 8px 0 0; color: var(--moss); font-size: 14px; }

.units { display: flex; gap: 8px; margin-top: 12px; }
.unit { flex: 1; min-height: var(--tap); font-size: 16px; }
.unit.on {
  background: var(--pine);
  border-color: var(--pine);
  color: var(--bone);
  font-weight: 700;
}

.section-total {
  margin: 0;
  color: var(--moss);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Quiet row at the bottom of the lists screen: who is signed in, sync
   state, and Sign out. Deliberately understated — this is not a feature,
   it is bookkeeping. */
.account-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  color: var(--moss);
  font-size: 14px;
}
.account-email, .account-sync { overflow-wrap: anywhere; }
.account-row button { margin-left: auto; font-size: 15px; font-weight: 400; }

/* Delete my data sits on its own line under the account row, never beside
   Sign out: at 390px the two would end up a thumb-width apart, and only one
   of them can be undone by signing back in. */
.account-danger { margin: 14px 0 0; }

/* The conflict prompt (DESIGN.md 5.4). It sits above everything, including
   the Add Gear sheet, because a background push can 409 while that sheet is
   open. There is deliberately no backdrop-dismiss and no close button: the
   only two elements a tap can land on that do anything are the two choice
   buttons below. */
#conflict-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(22, 44, 34, 0.6);
  z-index: 40;
}
#conflict-modal {
  position: fixed;
  left: 12px;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  max-width: 406px;
  margin: 0 auto;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--paper);
  border-radius: 16px;
  z-index: 41;
  box-shadow: 0 4px 28px rgba(22, 44, 34, 0.4);
}
#conflict-backdrop[hidden], #conflict-modal[hidden] { display: none; }

.conflict-inner { padding: 20px var(--pad); }
.conflict-inner h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.01em;
  margin: 0 0 10px;
}
.conflict-inner p { margin: 0 0 var(--pad); }

.conflict-choice { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.conflict-choice button {
  min-height: 64px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  text-align: left;
}
.conflict-choice-label { font-size: 17px; font-weight: 700; }
.conflict-choice-detail { font-size: 14px; font-weight: 400; color: var(--moss); }
/* The primary (filled, pine) button reads as distinct from the plain
   (outlined, white) one at a glance — the same visual language the app
   already uses for Save vs. Cancel in the Add Gear sheet. */
.conflict-choice button.primary .conflict-choice-detail { color: rgba(238, 230, 214, 0.85); }

/* Privacy and Terms, under the account row. Inline links, but still real
   tap targets: 44px minimum applies to anything you are meant to hit. */
.legal-links {
  display: flex;
  gap: 8px;
  margin: 4px 0 24px;
}
.legal-links a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 12px;
  color: var(--moss);
  font-size: 15px;
}

/* The paywall and read-only mode (DESIGN.md 5.2).

   Deliberately quiet. Nothing here flashes, counts down, or changes colour
   as a deadline approaches — honest copy with no dark patterns is a
   standing rule, and this is the screen where breaking it would be most
   tempting. The read-only banner reuses the same quiet .banner the app
   already uses for ordinary information, because that is what it is. */
.banner.readonly p { margin: 0 0 12px; }
.banner.readonly button { width: 100%; }

/* The preview banner (?paywall=preview). Visually unlike everything else on
   purpose: it must be impossible to mistake for real account state, so it is
   the one thing on screen that is not part of the palette. */
.banner.preview {
  background: #EFEAF7;
  border-color: #BFAEE0;
  border-left-color: #7A5CA8;
  color: var(--ink);
}

/* The trial notice sits in the ordinary muted hint style and collapses to
   nothing when empty, so an unstyled gap never appears where it will be. */
.trial-notice:empty { display: none; }

.price {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 14px;
  margin: 0 0 var(--pad);
}
.price strong {
  font-family: var(--display);
  font-weight: 700;
  font-size: 22px;
  font-variant-numeric: tabular-nums;
}
.price span { color: var(--moss); font-size: 15px; }

/* ---------- the example templates (DESIGN.md 5.2.2) ----------

   Three screens: the signed-out front door, the browse grid for someone
   already signed in, and one template read end to end.

   The preview rows carry their own class names — .tpl-item, .tpl-box —
   rather than reusing .item and .box. Those two already mean something on
   the list screens (a tappable gear row, and the 26px packing checkbox),
   and quietly redefining them would repaint every list in the app. */

/* The front door. The only dark panel in the product: the app names itself
   here, and nowhere else does a whole block of pine read as anything but
   tiring. */
.hero {
  background: var(--pine-deep);
  color: var(--bone);
  padding: 22px var(--pad) 26px;
}
.lockup { display: flex; align-items: center; gap: 9px; margin-bottom: 20px; }
/* The mark at hero size — the silhouette beside the wordmark, the same
   lockup the header bars use, never the rounded launcher tile. */
.lockup .mk-lg { width: 34px; height: 34px; flex: none; display: block; }
.lockup .name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 25px;
  letter-spacing: -0.015em;
  margin: 0;
}
.hero .pitch {
  font-family: var(--display);
  font-weight: 600;
  font-size: 25px;
  line-height: 1.22;
  letter-spacing: -0.012em;
  margin: 0 0 20px;
  max-width: 13em;
}
/* On pine-deep the primary green would disappear, so the button inverts:
   bone fill, deep green text. */
.hero button.on-dark {
  background: var(--bone);
  border-color: var(--bone);
  color: var(--pine-deep);
}
/* Reads as a link, sized as a button: 44px minimum applies to anything
   anyone is meant to hit, links included. */
.hero .quiet-link {
  display: block;
  width: 100%;
  margin-top: 4px;
  background: transparent;
  border: 0;
  color: var(--bone);
  opacity: 0.75;
  font-weight: 400;
  font-size: 15.5px;
}

.lbl {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moss);
  margin: 0 0 10px;
}

/* Two across. A grid only beats a stack while the tiles stay short, which
   is why a tile carries a name and one line of facts and nothing else —
   and the advantage grows as templates are added. */
.tgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ttile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-height: 76px;
  text-align: left;
  padding: 13px 14px;
}
.ttile b {
  font-family: var(--display);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.2;
  letter-spacing: -0.005em;
  overflow-wrap: anywhere;
}
.ttile span {
  font-size: 13px;
  font-weight: 400;
  color: var(--moss);
  font-variant-numeric: tabular-nums;
}

/* The honest price line, in the same muted register as every other hint.
   It states what this costs and that nothing can charge anyone yet. */
.landing-price { color: var(--moss); font-size: 14.5px; margin: 18px 0 0; }

/* The template's own days-and-items line, in the header bar beside its
   name. .bar h1 is flex:1, so this sits hard right. */
.bar .bar-sub { font-size: 13px; opacity: 0.78; flex: none; }

/* One template, read end to end. Tighter than a real list because nothing
   here is tappable: it is a document, not a screen of controls. */
.tpl-sect { margin-bottom: 20px; }
.tpl-sect-h {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--rule);
}
.tpl-sect-h b {
  font-family: var(--display);
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: -0.005em;
  overflow-wrap: anywhere;
}
.tpl-sect-h span {
  font-size: 13px;
  color: var(--moss);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tpl-items { list-style: none; margin: 0; padding: 0; }
.tpl-item {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 6px 0;
  font-size: 15.5px;
}
/* An empty box, drawn in CSS like the packing checkbox and for the same
   reason: nothing is fetched to draw it. Smaller and quieter than the real
   one, because this one cannot be ticked. */
.tpl-box {
  width: 17px;
  height: 17px;
  flex: none;
  align-self: center;
  border: 1.5px solid var(--faint);
  border-radius: 4px;
}
.tpl-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }

/* The way forward, always on screen however far down a twelve-section list
   someone has read. The caption is load-bearing: it is where "you will be
   asked to sign in first" is said, before the tap rather than after it. */
.sticky-cta {
  position: sticky;
  bottom: 0;
  background: var(--card);
  border-top: 1px solid var(--rule);
  padding: 12px var(--pad);
  padding-bottom: calc(12px + env(safe-area-inset-bottom));
}
.sticky-cta .why {
  font-size: 13px;
  color: var(--moss);
  text-align: center;
  margin: 8px 0 0;
}

/* Two stacked full-width buttons — "+ New list" and "Start from an example
   list" — would otherwise touch and read as one control. */
.pad > button.big + button.big { margin-top: 10px; }

/* The way back off the sign-in screen, to the example lists. Quiet: it is
   an escape hatch, not a second offer. */
.signin-back { margin: 4px 0 0; }
.signin-back button { width: 100%; border: 0; background: transparent; color: var(--moss); font-weight: 400; }
