/* ══════════════════════════════════════════════════════════════════════════
   MUSTER — TM 9-1005, the field manual design system.

   The conceit is structural, not decorative: a challenge coin arrives with a
   story nobody ever writes down, and a field manual is the document type that
   exists to write things down. So a coin is a numbered PLATE with a caption
   block, and its story is the REMARKS field.

   No build step, no webfonts, no images. The paper grain, the punch holes and
   the wire coil are all drawn in CSS: a texture JPEG would be the single
   heaviest asset in the app and this has to feel instant on a phone.
   ══════════════════════════════════════════════════════════════════════════ */

/* IBM Plex Mono (OFL) — the face the high-res frames are actually set in:
   a sans-serif mono. The style-guide panel says Courier Prime; the screens
   do not use it. Self-hosted, Latin subset, 400/500/700. */
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/fonts/IBMPlexMono-400.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/fonts/IBMPlexMono-500.woff2') format('woff2'); }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url('/fonts/IBMPlexMono-700.woff2') format('woff2'); }

/* Courier Prime (OFL) — the logbook's typewriter face, for everything that
   is "typed into the book": headings, captions, data, labels. Self-hosted,
   Latin subset, regular + bold; the same TTFs feed the GD share card. */
@font-face {
  font-family: 'Courier Prime'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('/fonts/CourierPrime-Regular.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Courier Prime'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('/fonts/CourierPrime-Bold.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Black Ops One — a real stencil face for the cover title.
   SELF-HOSTED rather than linked from Google Fonts: one fewer third-party
   request, no external dependency on a page that must render on a phone in a
   parking lot, and the same file feeds the GD share card so the web page and
   the shared image cannot drift apart. OFL licensed.
   Used with restraint — the cover title only. Everywhere else stays monospace
   or condensed, or the stencil stops meaning anything. */
@font-face {
  font-family: 'Black Ops One';
  font-style: normal;
  font-weight: 400;
  font-display: swap;   /* the cover must render before the font arrives */
  src: url('/fonts/BlackOpsOne-Regular.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Kraft manual stock. Aged, warm, slightly green-shifted. */
  --paper:      #F1E7CA;
  --paper-hi:   #F1E7CA;   /* boxes sit on the same paper in this design */
  --paper-low:  #DCD2B8;   /* shadowed gutter near the binding */
  --stain:      rgba(120, 84, 30, 0.16);   /* old coffee, thinned */
  --tab-od:     #5A6547;   /* index tab green */
  --tab-od-lo:  #465039;

  --ink:        #1E1E1B;   /* near-black, a typewriter's full strike */
  --ink-soft:   #3A3B35;   /* secondary text is still dark in this design */
  --ink-faint:  #8A8B72;   /* rule lines, dotted leaders, disabled */

  --od:         #4C5540;   /* olive drab, the structural green */
  --od-deep:    #333B29;
  --stencil:    #6E7A57;   /* spray-through-a-plate green */
  --stamp:      #8C3A2B;   /* faded red rubber stamp. The ONE accent. */
  --brass:      #A8843C;   /* the coins themselves */

  /* The cover panel. Drawn from the olive-field manual covers: a drab green
     field, gold rules, and pale stencil type sprayed over the top. */
  --od-panel:   #454F3A;   /* the olive field the cover sits on */
  --gold:       #C9A227;   /* the rule around it */
  --stencil-hi: #E8DC9A;   /* pale stencil yellow, for the title */
  --stencil-lo: #D2C489;   /* muted stencil yellow, for the small tracked caps */

  --rule:       rgba(35, 38, 26, 0.22);
  --rule-hard:  rgba(35, 38, 26, 0.55);

  --stencil-face: 'Black Ops One', "Arial Narrow", Impact, system-ui, sans-serif;
  --head:  'IBM Plex Mono', 'Courier Prime', ui-monospace, Menlo, monospace;
  --cond:  "Arial Narrow", "Helvetica Neue Condensed", "Liberation Sans Narrow", Haettenschweiler, Impact, system-ui, sans-serif;
  --mono:  'IBM Plex Mono', 'Courier Prime', ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;

  /* One control height for every single-line field, so inputs and selects
     line up. Native selects render shorter than inputs unless you say so. */
  --control-h: 2.75rem;
  --bind: 2.5rem;          /* width of the spiral binding gutter */
  --radius: 2px;           /* paper does not have rounded corners */
}

/* NO DARK MODE, deliberately.
 *
 * There was one: it flipped --ink to a phosphor green and --paper to dark
 * olive. It broke the moment the design committed to real paper. Every surface
 * in this app is now a cream IMAGE — paper-tile.jpg on the body, the polaroid
 * card PNGs, the grain overlay — and an image paints straight over whatever
 * --paper is set to. So on a phone in dark mode the ink went pale while the
 * paper stayed cream, and the whole app rendered washed out. Measured:
 * --ink #C8D0AC over a body still painting paper-tile.jpg.
 *
 * A real dark mode here is not a token swap, it is a second set of paper,
 * card, tape and grain art. Until that exists this is a printed field manual,
 * and paper does not have a night mode. `color-scheme: light` also stops iOS
 * inverting form controls and scrollbars underneath us.
 */
:root {
  color-scheme: light;
  /* Every safe-area read goes through these. env() cannot be overridden, so a
     test can never simulate a home-indicator phone — which is exactly how the
     lopsided tab bar shipped. A custom property CAN be overridden. */
  --sat: env(safe-area-inset-top);
  --sab: env(safe-area-inset-bottom);
}

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

body {
  margin: 0;
  background-color: var(--paper);
  /* Organic paper: a seamless 1024px tile of layered value noise with a
     fiber octave, rendered by tools/make-paper.php. Shown at 512px CSS so
     retina gets full detail. 40KB once, cached a week. */
  background-image: url('/assets/paper-tile.jpg');
  background-size: 512px 512px;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
  /* iOS zooms any focused field under 16px and the page then scrolls
     sideways for the rest of the session. Fields opt back up in .field. */
}

/* ── Stencil heads ─────────────────────────────────────────────────────────
   Sprayed through a cut plate: wide tracking, heavy weight, never italic. */
.stencil {
  font-family: var(--mono);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--stencil);
}
.stencil-lg { font-size: 1.05rem; letter-spacing: 0.22em; }
.stencil-sm { font-size: 0.7rem;  letter-spacing: 0.16em; color: var(--ink-soft); }

/* The manual's running head: TM number left, page/section right, rule under. */
.runhead {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding-bottom: 0.4rem;
  border-bottom: 1.5px solid var(--rule-hard);
  font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-soft);
}

/* ── The sheet + its spiral binding ────────────────────────────────────────
   Punch holes are drawn down the gutter with a repeating radial gradient; the
   coil is a second repeating gradient of short diagonal strokes crossing the
   edge. Both are one element, so a long page never runs out of holes. */
.sheet {
  position: relative;
  background: var(--paper-hi);
  border: 1px solid var(--rule-hard);
  border-radius: var(--radius);
  padding: 1.1rem 1.1rem 1.1rem calc(var(--bind) + 0.6rem);
  box-shadow: 0 1px 0 rgba(0,0,0,0.10), 0 6px 14px -10px rgba(0,0,0,0.5);
}
.sheet::before {
  /* the gutter: a darker strip where the sheet curves into the coil */
  content: ""; position: absolute; inset: 0 auto 0 0; width: var(--bind);
  background:
    linear-gradient(90deg, var(--paper-low), rgba(0,0,0,0.05) 65%, transparent),
    repeating-radial-gradient(circle at calc(var(--bind) / 2) 1.1rem,
      var(--paper) 0 0.28rem, transparent 0.28rem);
  background-size: 100% 100%, 100% 2.2rem;
  border-right: 1px dashed var(--rule);
  pointer-events: none;
}
.sheet::after {
  /* the wire coil crossing the punched edge */
  content: ""; position: absolute; inset: 0 auto 0 0; width: var(--bind);
  background: repeating-linear-gradient(
    -24deg,
    transparent 0 0.62rem,
    var(--ink-faint) 0.62rem 0.72rem,
    transparent 0.72rem 2.2rem);
  -webkit-mask-image: linear-gradient(90deg, #000 0 62%, transparent 78%);
          mask-image: linear-gradient(90deg, #000 0 62%, transparent 78%);
  opacity: 0.75; pointer-events: none;
}

/* ── PLATE: one coin, one numbered figure in the manual ───────────────────*/
.plate { position: relative; padding-block: 0.9rem; border-bottom: 1px solid var(--rule); }
.plate:last-child { border-bottom: 0; }
.plate-no {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-faint);
}
.plate-title {
  margin: 0.15rem 0 0.1rem; font-size: 1rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink);
}
.plate-issuer { font-size: 0.78rem; color: var(--ink-soft); }

/* The two faces. A coin is a disc and it has two sides; showing one is
   showing half the artwork. */
.faces { display: flex; gap: 0.75rem; margin: 0.7rem 0; }
.face {
  position: relative; flex: 0 0 auto; width: 5.5rem; height: 5.5rem;
  border-radius: 50%; overflow: hidden;
  background: var(--paper);
  border: 1.5px solid var(--rule-hard);
  box-shadow: inset 0 0 0 3px var(--paper-hi), inset 0 0 12px -4px rgba(0,0,0,0.55);
  display: grid; place-items: center;
}
.face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.face-label {
  position: absolute; bottom: 0; left: 0; right: 0;
  font-size: 0.55rem; letter-spacing: 0.14em; text-transform: uppercase;
  text-align: center; padding: 0.12rem 0;
  background: rgba(35,38,26,0.62); color: #E7E2CE;
}
.face-empty { font-size: 0.58rem; letter-spacing: 0.12em; color: var(--ink-faint); text-transform: uppercase; }

/* ── Caption block: dotted leaders, the manual's label-to-value device ─────*/
.caption { margin: 0; font-size: 0.8rem; }
.caption div {
  display: flex; align-items: baseline; gap: 0.4rem;
  padding: 0.12rem 0; color: var(--ink-soft);
}
.caption dt, .caption .k {
  flex: 0 0 auto; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.68rem;
}
.caption .lead {
  flex: 1 1 auto; height: 0.62em;
  border-bottom: 1px dotted var(--ink-faint);
}
.caption dd, .caption .v { flex: 0 0 auto; margin: 0; color: var(--ink); text-align: right; }

/* REMARKS — the provenance. Set in serif because a manual sets running prose
   differently from tabular data, and because this is the one field a person
   actually rereads years later. */
.remarks {
  margin: 0.6rem 0 0; padding: 0.55rem 0.7rem;
  font-family: var(--mono); font-size: 0.95rem; line-height: 1.6;
  color: var(--ink);
  background-image: linear-gradient(var(--rule) 1px, transparent 1px);
  background-size: 100% 1.55em;
  background-position: 0 1.54em;
  border-left: 2px solid var(--od);
}
.remarks-head {
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.2rem;
}

/* ── THE SIGNATURE: rubber stamps ──────────────────────────────────────────
   Status is never a pill. It is struck across the plate at an angle, outlined,
   and worn through — the way a clerk marks a page. All the boldness in this
   design is spent here, so everything around it stays quiet. */
.stamp {
  display: inline-block; transform: rotate(-8deg);
  padding: 0.22rem 0.6rem;
  font-family: var(--mono); font-weight: 700; font-size: 0.7rem;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--stamp);
  border: 2.5px solid var(--stamp);
  border-radius: 3px;
  opacity: 0.9;
  /* Worn through: the ink never covers the whole face of the stamp. */
  -webkit-mask-image: repeating-linear-gradient(64deg, #000 0 9px, rgba(0,0,0,0.62) 9px 11px);
          mask-image: repeating-linear-gradient(64deg, #000 0 9px, rgba(0,0,0,0.62) 9px 11px);
}
.stamp-od { color: var(--od); border-color: var(--od); }
.stamp-faint { color: var(--ink-faint); border-color: var(--ink-faint); opacity: 0.6; }
.stamp-corner { position: absolute; top: 0.7rem; right: 0; }


/* The data block. Reads like a manual's tabulated summary, not a row of
   dashboard cards. Lives here rather than in app.css because the public case
   page uses it too and only ever loads this stylesheet. */
.statline {
  display: flex; flex-wrap: wrap; gap: 0 1.1rem;
  padding: 0.5rem 0; margin-bottom: 0.3rem;
  border-block: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft);
}
.statline b { color: var(--ink); font-variant-numeric: tabular-nums; }

.empty-head {
  font-family: var(--head); font-weight: 700;
  font-size: 1.1rem; letter-spacing: 0.08em; text-transform: uppercase; margin: 0 0 0.35rem;
}

/* ── Controls ─────────────────────────────────────────────────────────────*/
.field { display: block; margin-bottom: 0.85rem; }
.field > span {
  display: block; margin-bottom: 0.28rem;
  font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-soft);
}
/* Every single-line control shares one height. A native select renders
   shorter than a text input unless it is told otherwise, and a form where the
   selects sit a few pixels short of the inputs looks broken without anyone
   being able to say why. Textareas are deliberately excluded. */
.field input, .field select {
  height: var(--control-h);
}
.field input, .field select, .field textarea {
  width: 100%; display: block;
  padding: 0 0.6rem;
  font-family: var(--mono);
  font-size: 16px;              /* under 16px iOS zooms on focus */
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-hard);
  border-radius: var(--radius);
  appearance: none; -webkit-appearance: none;
}
.field textarea { padding: 0.5rem 0; min-height: 7rem; font-family: var(--mono); font-size: 16px; line-height: 1.6; resize: vertical; }
.field select {
  /* the chevron, drawn rather than fetched */
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%),
                    linear-gradient(135deg, var(--ink-soft) 50%, transparent 50%);
  background-position: right 1.05rem center, right 0.75rem center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 2rem;
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible,
button:focus-visible, a:focus-visible {
  outline: 2px solid var(--od); outline-offset: 2px;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  min-height: var(--control-h); padding: 0 1rem;
  font-family: var(--mono); font-size: 0.78rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--paper-hi); background: var(--od);
  border: 1px solid var(--od-deep); border-radius: var(--radius);
  cursor: pointer; text-decoration: none;
}
.btn:hover { background: var(--od-deep); }
.btn-ghost { color: var(--ink); background: transparent; border-color: var(--rule-hard); }
.btn-ghost:hover { background: rgba(0,0,0,0.05); }
.btn-danger { color: var(--stamp); background: transparent; border-color: var(--stamp); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* A text link, not a button, for the sign-in/sign-up swap. */
.link-swap {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 0.8rem; color: var(--od);
  text-decoration: underline; text-underline-offset: 3px;
}

/* ── Utility ──────────────────────────────────────────────────────────────*/
.wrap { max-width: 46rem; margin: 0 auto; padding: 1rem; }
.muted { color: var(--ink-soft); }
.tabular { font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
hr.rule { border: 0; border-top: 1px solid var(--rule); margin: 1rem 0; }
hr.rule-hard { border: 0; border-top: 1.5px solid var(--rule-hard); margin: 1rem 0; }

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

/* ══════════════════════════════════════════════════════════════════════════
   COVER DEVICES — drawn from FM 21-150 (1942) and TM 55-1940-205-34.

   The single most recognisable thing about a real manual cover is not the
   colour, it is the RULE BOX: a heavy outer rule with a hairline inner rule a
   few millimetres inside it, wrapped around centred, stacked, all-caps lines.
   Everything else on those covers is restraint.
   ══════════════════════════════════════════════════════════════════════════ */
.rulebox {
  position: relative;
  padding: 1.4rem 1.2rem;
  text-align: center;
  border: 3px solid var(--gold);
  background: var(--od-panel);
}
.rulebox::before {
  content: ""; position: absolute; inset: 4px;
  border: 1px solid var(--gold);
  pointer-events: none;
}
.rulebox > * { position: relative; }

/* Stacked cover lines. Each is its own line, centred, caps, and the sizes step
   the way a cover steps: issuing body small, title large, qualifier medium. */
.cover-body  { font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.28em; text-transform: uppercase; color: var(--stencil-lo); }
.cover-title {
  font-family: var(--stencil-face); font-weight: 400;
  /* Black Ops One is already heavy and wide; it needs a touch more tracking
     and less size than the condensed fallback to sit in the same box. */
  font-size: clamp(1.9rem, 9.5vw, 3.1rem); line-height: 1.05;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--stencil-hi);
  margin: 0.6rem 0 0.45rem;
}
.cover-sub   { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--stencil-lo); }
.cover-rule  { width: 3.5rem; height: 2px; background: var(--gold); border: 0; margin: 0.7rem auto; }

/* The designation, set out on its own the way "FM 21-150" sits above the box. */
.fm-no {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--ink-soft);
}

/* Section head: a rule, the head, a rule. Used between manual sections. */
.section-head {
  display: flex; align-items: center; gap: 0.7rem;
  margin: 1.6rem 0 0.8rem;
  font-family: var(--head); font-weight: 700;
  font-size: 1.05rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink);
}
.section-head::before, .section-head::after { content: ""; height: 2px; background: var(--rule-hard); flex: 1 1 auto; }
.section-head::before { flex: 0 0 1.2rem; }

/* ══════════════════════════════════════════════════════════════════════════
   THE PLATE GRID — the hand-signals-chart pattern.

   A real manual teaches a set of things by drawing each one in its own ruled
   panel and captioning it underneath, in a grid. That is exactly the shape of
   a rack of coins, and it beats a vertical list on a phone: two columns of
   discs scan in one glance, the way the rack on the wall does.
   ══════════════════════════════════════════════════════════════════════════ */
.plate-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.7rem;
  margin: 0.9rem 0;
}
.plate-cell {
  position: relative;
  display: flex; flex-direction: column;
  background: #F3EDDA;
  border: 1.5px solid var(--ink);
  border-radius: 0;
  padding: 0.5rem 0.5rem 0;
  cursor: pointer;
  text-align: left;
  font: inherit; color: inherit;
  appearance: none; -webkit-appearance: none;
}
.plate-cell:hover  { background: var(--paper); }
.plate-cell:focus-visible { outline: 2px solid var(--od); outline-offset: 2px; }

/* The disc sits in the panel, centred, with air around it like a plate figure. */
.plate-figure {
  position: relative;
  aspect-ratio: 1 / 1;
  display: grid; place-items: center;
  margin-bottom: 0.45rem;
}
.plate-figure .face { width: 100%; height: 100%; }

/* Caption bar: ruled off from the figure, exactly like a plate caption. */
.plate-caption {
  border-top: 1px solid var(--ink);
  margin: 0 -0.5rem; padding: 0.4rem 0.45rem 0.5rem;
  min-height: 2.9rem; text-align: center;
}
.plate-caption .no {
  font-family: var(--mono); font-size: 0.55rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint);
}
.plate-caption .nm {
  font-family: var(--head); font-weight: 700;
  font-size: 0.64rem; line-height: 1.25; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.plate-caption .by { font-family: var(--mono); font-size: 0.6rem; color: var(--ink-soft); }

/* A carried coin gets the red mark on its panel, small, in the corner. */
.plate-cell .stamp-corner { top: 0.3rem; right: 0.3rem; font-size: 0.5rem; padding: 0.1rem 0.3rem; border-width: 1.5px; letter-spacing: 0.14em; }

/* ── Line-art plate figures ───────────────────────────────────────────────
   Stroke-only SVG, no fills, drawn at the weight the reference charts use. */
.linework { width: 100%; height: 100%; display: block; }
.linework * { fill: none; stroke: var(--ink); stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.linework .fill-od { fill: var(--label); stroke: none; }
.linework .thin { stroke-width: 3.9; }
.linework .accent { stroke: var(--stamp); }

/* Decorations: the paperclip and the coffee ring. Both are ornaments on a
   page, never interactive. */
.paperclip {
  position: absolute; top: -0.6rem; left: 1.2rem; width: 1.1rem; height: 3.2rem;
  pointer-events: none; z-index: 2;
}
.paperclip * { fill: none; stroke: #8A8F86; stroke-width: 2.2; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.coffee-ring {
  position: absolute; width: 7.5rem; height: 7.5rem; border-radius: 50%;
  pointer-events: none; opacity: 0.55;
  border: 0.55rem solid transparent;
  background:
    radial-gradient(circle, transparent 58%, rgba(120,84,30,0.22) 60%, rgba(120,84,30,0.10) 66%, transparent 70%) border-box,
    radial-gradient(circle, transparent 56%, rgba(120,84,30,0.35) 57%, transparent 59%) border-box;
  transform: rotate(-12deg);
}
/* A red inventory number, stamped. */
.serial-stamp {
  position: absolute; top: 0.9rem; right: 0.9rem;
  padding: 0.12rem 0.4rem;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em;
  color: var(--stamp); border: 2px solid var(--stamp); border-radius: 2px;
  transform: rotate(3deg); opacity: 0.85;
  -webkit-mask-image: repeating-linear-gradient(64deg, #000 0 9px, rgba(0,0,0,0.62) 9px 11px);
          mask-image: repeating-linear-gradient(64deg, #000 0 9px, rgba(0,0,0,0.62) 9px 11px);
}
/* Ruled-paper list: the logbook page. */
.ruled { background-image: linear-gradient(var(--rule) 1px, transparent 1px); background-size: 100% 2.4rem; }
.ruled-row {
  display: grid; grid-template-columns: 4.4rem 1fr 2.6rem; gap: 0.6rem; align-items: center;
  min-height: 2.4rem; padding: 0.3rem 0;
  border: 0; background: none; width: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit;
}
.ruled-row .d { font-family: var(--mono); font-size: 0.68rem; color: var(--ink-soft); border-bottom: 1px solid var(--ink-faint); padding-bottom: 0.1rem; }
.ruled-row .t { font-family: var(--head); font-weight: 700; font-size: 0.74rem; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.2; }
.ruled-row .p { font-family: var(--mono); font-size: 0.64rem; color: var(--ink-soft); }
.ruled-row .face { width: 2.4rem; height: 2.4rem; }

/* ══════════════════════════════════════════════════════════════════════════
   CLASSIC FIELD GUIDE — Jesse's reference, frame by frame.
   Courier Prime throughout. Bordered boxes, 1px ink rules, line icons,
   dark coin tiles, a bottom tab bar. Clean, structured, timeless.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  /* ONE olive drab, used by the tab bar wash, the FAB, and every solid
     button — Jesse: "we're gonna use it for buttons too". */
  --fg-olive: #3E4A33; --fg-olive-deep: #2C3625; --fg-sage: #8C9A86; --fg-tile: #1F2219; --bar-h: 4.1rem;
}
.fg-body { padding: calc(var(--sat)) 0 calc(var(--bar-h) + var(--sab)); }
.fg-wrap { max-width: 30rem; margin: 0 auto; padding: 0.6rem 1.1rem 1.4rem; }

/* TM number: top centred, bottom right with a rule running off the page */
.tm { text-align: center; font-family: var(--mono); font-size: 0.95rem; letter-spacing: 0.04em; color: var(--ink); margin: 0.6rem 0 1.6rem; }
.tm-foot { display: flex; align-items: center; justify-content: flex-end; gap: 0.9rem; margin: 1.6rem -1.1rem 0 0; font-family: var(--mono); font-size: 0.95rem; color: var(--ink); }
.tm-foot::after { content: ""; width: 2.6rem; height: 1.5px; background: var(--ink); }

/* Screen header: chevron, TITLE, count under, icon right */
.ph { display: flex; justify-content: space-between; align-items: flex-start; margin: 0.4rem 0 1rem; }
.ph .ph-l { display: flex; align-items: flex-start; gap: 0.55rem; }
.ph .back { appearance: none; background: none; border: 0; padding: 0 0.1rem 0 0; cursor: pointer; color: var(--ink); font-family: var(--mono); font-size: 1.75rem; font-weight: 500;
  /* center the glyph on the TITLE's first line (1.6rem * 1.15 line box), and
     lift it slightly: the ‹ sits low in Plex Mono's em box */
  line-height: 1.84rem; position: relative; top: -0.09em; }
.ph h2 { margin: 0; font-family: var(--head); font-weight: 700; font-size: 1.6rem; letter-spacing: 0.03em; text-transform: uppercase; line-height: 1.15; }
.ph .cnt { font-family: var(--mono); font-size: 0.95rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink-soft); margin-top: 0.2rem; }
.ph .ph-ico { width: 1.9rem; height: 1.9rem; background: none; border: 0; padding: 0; cursor: pointer; color: var(--ink); margin-top: 0.15rem; }
.ph .ph-ico .linework { width: 100%; height: 100%; }
/* ── Icon weight system ──────────────────────────────────────────────────
   SVG stroke scales with rendered size, so one global width renders 1.2px
   thin on a chevron and 5px fat on a hero figure. Every context below pins
   the OPTICAL weight to ~1.8px (detail `.thin` lines at ~65% of that):
       vb-stroke = 1.8 * 100 / rendered-px
   If you add an icon context, add its row here; do not reuse a neighbour's
   number at a different size. */
.linework * { stroke-width: 6; }                      /* default assumes ~30px */
.linework .thin { stroke-width: 3.9; }

/* Home: FIELD GUIDE */
.fg-title { font-family: var(--head); font-weight: 700; font-size: 2.55rem; letter-spacing: 0.035em; text-transform: uppercase; margin: 0; line-height: 1.1; }
.fg-sub { font-family: var(--mono); font-size: 1.2rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink); margin: 0.35rem 0 2.1rem; }

/* The bordered menu list */
.menu { border: 1.5px solid var(--ink); border-radius: 7px; background: transparent; overflow: hidden; }
.menu button, .menu a {
  display: grid; grid-template-columns: 3.4rem 1fr; gap: 1.4rem; align-items: center;
  width: 100%; appearance: none; background: none; border: 0; border-bottom: 1.5px solid var(--ink);
  padding: 1.35rem 1.3rem 1.35rem 1.45rem; cursor: pointer; text-align: left; color: var(--ink); font: inherit; text-decoration: none;
}
.menu button:last-child, .menu a:last-child { border-bottom: 0; }
.menu .linework { width: 3.4rem; height: 3.4rem; }
.menu .linework * { stroke-width: 3.3; }
.menu .linework .thin { stroke-width: 2.1; }
.menu .mt { font-family: var(--head); font-weight: 700; font-size: 1.5rem; letter-spacing: 0.02em; text-transform: uppercase; line-height: 1.15; }
.menu .ms { font-family: var(--mono); font-size: 1.08rem; color: var(--ink); margin-top: 0.3rem; }

/* PROPERTY OF box */
.property { display: flex; justify-content: space-between; align-items: center; gap: 1rem; border: 1.5px solid var(--ink); border-radius: 7px; background: transparent; padding: 1.1rem 1.5rem 1.2rem; margin-top: 1.7rem; }
.property .pl { font-family: var(--mono); font-size: 0.98rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ink); }
.property .pn { font-family: var(--head); font-weight: 700; font-size: 1.55rem; letter-spacing: 0.02em; text-transform: uppercase; margin-top: 0.2rem; line-height: 1.1; }
/* the little unit-number glyph: U | O over a star, in an open-topped box */
.property .stampbox { position: relative; width: 3.3rem; height: 3.1rem; border: 1.5px solid var(--ink); border-top: 0; display: grid; place-items: start center; padding-top: 0.25rem;
  font-family: var(--mono); font-size: 1.05rem; letter-spacing: 0.05em; color: var(--ink); transform: none; line-height: 1; }
.property .stampbox::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; width: 1.5px; background: var(--ink); height: 55%; }
.property .stampbox::after { content: "\2605"; position: absolute; left: 0; right: 0; bottom: 0.15rem; text-align: center; font-size: 0.8rem; border-top: 1.5px solid var(--ink); margin: 0 0.3rem; padding-top: 0.1rem; }

/* Search field: rounded, tall, magnifier left, sliders right */
.searchbar { position: relative; margin: 0.6rem 0 1.6rem; }
.searchbar input { width: 100%; height: 3.5rem; padding: 0 3rem 0 3.2rem; border: 1.5px solid var(--ink); border-radius: 8px; background: transparent;
  /* 17px, not 16 — under 16 iOS zooms the field and the app "scrolls sideways". */
  font-family: var(--mono); font-size: 17px; color: var(--ink); appearance: none; }
.searchbar input::placeholder { color: var(--ink); opacity: 0.85; }
.searchbar .sb-ico { position: absolute; top: 50%; transform: translateY(-50%); width: 1.5rem; height: 1.5rem; color: var(--ink); background: none; border: 0; padding: 0; }
.searchbar .sb-ico.l { left: 1rem; pointer-events: none; }
.searchbar .sb-ico.r { right: 1rem; cursor: pointer; }

/* Collection grid: dark rounded tiles, big coin, bold caption below-left */
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 1.3rem 1.35rem; padding: 0 0.1rem; }
.tile { appearance: none; background: none; border: 0; padding: 0; cursor: pointer; text-align: left; color: inherit; font: inherit; position: relative; }
.tile .sq { aspect-ratio: 1 / 1; background: #1E2119; border-radius: 6px; display: grid; place-items: center; padding: 9%; }
.tile .sq img { width: 100%; height: 100%; object-fit: contain; display: block; filter: drop-shadow(0 4px 5px rgba(0,0,0,0.55)); }
.tile .sq .face { width: 100%; height: 100%; }
.tile .cap { font-family: var(--head); font-weight: 700; font-size: 1.06rem; letter-spacing: 0.01em; text-transform: uppercase; line-height: 1.3; margin-top: 0.8rem; }
.tile .cap2 { font-family: var(--mono); font-size: 0.8rem; color: var(--ink-soft); margin-top: 0.15rem; }
.tile .stamp-corner { top: 0.5rem; right: 0.5rem; font-size: 0.52rem; padding: 0.1rem 0.3rem; border-width: 1.5px; z-index: 1; }

/* Floating + */
.fab { position: fixed; right: 1.2rem; bottom: calc(var(--bar-h) + var(--sab) + 0.3rem); z-index: 31;
  width: 4.6rem; height: 4.6rem; border-radius: 50%; display: grid; place-items: center;
  /* Olive INK on paper, not a plastic chip: a translucent wash over the
     page's own texture, so the grain reads through and the button belongs to
     the same surface as everything else. (This rule also still carried a
     hardcoded #4E5A3E after the olive was tokenised.) */
  color: #F6F1DE;
  background: url('/assets/grain.png') 0 0 / 380px 380px, var(--fg-olive);
  border: 1.5px solid rgba(30, 30, 27, 0.4); cursor: pointer;
  box-shadow: 0 6px 14px -6px rgba(0,0,0,0.45); }
.fab .plus { width: 2.05rem; height: 2.05rem; display: block; }
.fab .plus line { stroke: #F6F1DE; stroke-width: 8.5; stroke-linecap: round; }
.fab:active { background-color: var(--fg-olive-deep); }

/* Bottom tab bar: five line icons with labels */
:root { --bar-h: 5.3rem; }
/* A very faint olive wash sets the bar off from the page while keeping the
   paper texture: the tint is a gradient layer ABOVE the tile, not a solid
   fill (a solid would hide the grain). */
/* The bar is a nylon webbing strap: generated tape (tools/make-webbing.php)
   with a row of stitching along each edge. The stitches are an IMAGE, not a
   dashed border — a dash is one flat colour, a stitch is a cylinder of thread
   lying on cloth. --fig-bg re-points the Collection icon's masking disc at
   the webbing; left as paper it reads as a pale hole punched in the icon. */
.tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  --fig-bg: #6B7355;
  background: url('/assets/webbing.png') 0 0 / 160px 240px;
  border-top: 0; color: #F2EEDC;
  box-shadow: inset 0 9px 12px -9px rgba(0,0,0,0.55), inset 0 -7px 10px -8px rgba(0,0,0,0.5);
  display: grid; grid-template-columns: repeat(5, 1fr);
  padding: max(1.5rem, calc(var(--sab) - 0.6rem)) 0; }
.tabbar::before, .tabbar::after { content: ''; position: absolute; left: 0; right: 0; height: 11px;
  background: url('/assets/stitch-2.png') 0 0 / 18px 11px repeat-x; pointer-events: none; }
/* Both rows 0.42rem from their OWN edge: a strap's stitching runs parallel
   to both sides. Lifting only the lower one by the safe-area inset put ~40px
   of webbing below it against 7px above — invisible in a browser, obvious on
   a home-indicator phone. */
.tabbar::before { top: 0.42rem; }
.tabbar::after { bottom: 0.42rem; }
.tabbtn { appearance: none; border: 0; background: none; cursor: pointer; display: grid; justify-items: center; gap: 0.1rem; padding: 0; color: #F2EEDC; text-shadow: 0 1px 1px rgba(0,0,0,0.42); }
/* .linework hardcodes stroke: var(--ink); on a dark strap the icons have to
   follow the button's colour like the labels do. */
.tabbar .linework *, .actions .linework * { stroke: currentColor; }
/* The masking disc behind the front coin: it has to be the surface it sits
   on, not paper. Only reachable because the icon is inlined, not <use>d. */
.linework .fig-mask { fill: var(--fig-bg, var(--paper)); }
/* vector-effect is NOT inherited, so <use>-based icons never pick up
   non-scaling-stroke from .linework * — their stroke-width:6 stays in viewBox
   units and scales down. Inlined shapes DO pick it up, making 6 real pixels of
   stroke on a 30px icon: a solid blob. Put the inlined one back on viewBox
   units so it matches every other icon. */
.fig-inline * { vector-effect: none; }
.tabbtn .linework { width: 1.9rem; height: 1.9rem; }
.tabbtn .linework * { stroke-width: 6; }
.tabbtn .linework .thin { stroke-width: 3.9; }
.tabbtn span { font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.01em; text-transform: uppercase; }
.tabbtn[aria-selected="true"] { color: #FFFDF4; }
.tabbtn[aria-selected="true"] .linework * { stroke: #FFFDF4; stroke-width: 7; }

/* Coin details */
:root { --label: #4B5340; }
.hero-wrap { text-align: center; margin: 0.2rem 0 0; }
.hero { width: 15.5rem; height: 15.5rem; margin: 0 auto; display: grid; place-items: center;
  touch-action: pan-y; -webkit-user-select: none; user-select: none; }
.hero img { width: 100%; height: 100%; object-fit: contain; -webkit-user-drag: none; filter: drop-shadow(0 8px 10px rgba(0,0,0,0.35)); }
.hero .face { width: 100%; height: 100%; }
.dots { display: flex; justify-content: center; gap: 0.55rem; margin: 1.3rem 0 1.6rem; }
/* The dot itself stays 0.62rem; the padding is an invisible 44px tap target. */
.dots i { width: 0.62rem; height: 0.62rem; border-radius: 50%; background: #8D8D7A;
  box-sizing: content-box; padding: 0.9rem 0.55rem; background-clip: content-box; cursor: pointer; margin: -0.9rem -0.25rem; }
.dots i.on { background-color: var(--ink); }
.coin-name { font-family: var(--head); font-weight: 500; font-size: 1.75rem; letter-spacing: 0.01em; text-transform: uppercase; line-height: 1.25; margin: 0 0 1rem; }
.fields { margin: 0; border-top: 1.5px dotted var(--ink-faint); }
.fr { display: grid; grid-template-columns: 8.6rem 1fr; gap: 0.6rem; align-items: baseline; padding: 0.9rem 0; border-bottom: 1.5px dotted var(--ink-faint); }
.fr .fl { font-family: var(--mono); font-size: 1.05rem; letter-spacing: 0.01em; text-transform: uppercase; color: var(--label); }
.fr .fv { font-family: var(--mono); font-size: 1.05rem; color: var(--ink); text-transform: uppercase; letter-spacing: 0.01em; line-height: 1.45; }
.fr.notes { display: grid; }
.fr.notes .fv { text-transform: none; }
.fr.notes .fv .hl { background: none; }
.fr.notes .fv .nudge { font-style: normal; }

/* Action bar under a record: fixed to the foot of the screen, four up */
.actions { position: fixed; left: 0; right: 0; bottom: 0; z-index: 26; display: grid; grid-template-columns: repeat(4, 1fr); justify-items: center;
  --fig-bg: #6B7355;
  background: url('/assets/webbing.png') 0 0 / 160px 240px;
  border-top: 0; box-shadow: inset 0 9px 12px -9px rgba(0,0,0,0.55), inset 0 -7px 10px -8px rgba(0,0,0,0.5);
  padding: max(1.5rem, calc(var(--sab) - 0.5rem)) 0; margin: 0; }
.actions::before, .actions::after { content: ''; position: absolute; left: 0; right: 0; height: 11px;
  background: url('/assets/stitch-2.png') 0 0 / 18px 11px repeat-x; pointer-events: none; }
.actions::before { top: 0.42rem; }
.actions::after { bottom: 0.42rem; }
.actions button { appearance: none; background: none; border: 0; cursor: pointer; color: #F2EEDC; text-shadow: 0 1px 1px rgba(0,0,0,0.42); display: grid; justify-items: center; gap: 0.14rem;
  font-family: var(--mono); font-size: 0.9rem; letter-spacing: 0.01em; text-transform: uppercase; }
.actions .linework { width: 2rem; height: 2rem; }
.actions .linework * { stroke: #F2EEDC; stroke-width: 5.6; }

/* Logbook rows */
.ph .cnt { color: var(--label); }
.logrows { border: 1.5px solid var(--ink); border-radius: 7px; background: transparent; overflow: hidden; }
.logrow { display: grid; grid-template-columns: 6.7rem 1fr 5.6rem; gap: 0 1rem; align-items: center; width: 100%; appearance: none; background: none; border: 0; border-bottom: 1.5px solid var(--ink);
  padding: 0; min-height: 7.4rem; cursor: pointer; text-align: left; color: inherit; font: inherit; }
.logrow:last-child { border-bottom: 0; }
.logrow .dc { align-self: stretch; border-right: 1.5px solid var(--ink); padding: 1.15rem 0.6rem 1.15rem 0.75rem; }
.logrow .d { display: inline-block; font-family: var(--mono); font-size: 0.9rem; letter-spacing: 0.01em; border: 1.5px solid var(--ink); border-radius: 5px; padding: 0.3rem 0.45rem; }
.logrow .body { padding: 1.2rem 0; }
.logrow .t { font-family: var(--head); font-weight: 500; font-size: 1.18rem; letter-spacing: 0.01em; text-transform: uppercase; line-height: 1.25; }
.logrow .p { font-family: var(--mono); font-size: 0.98rem; color: var(--ink); margin-top: 0.6rem; }
.logrow .u { width: 66%; height: 0; border-bottom: 1.5px dashed var(--ink-faint); margin-top: 0.9rem; }
.logrow .th { width: 5.6rem; height: 5.6rem; display: grid; place-items: center; margin-right: 0.6rem; }
.logrow .th img { width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 3px 4px rgba(0,0,0,0.45)); }
.logrow .th .face { width: 100%; height: 100%; }

/* Stats: one rounded box holding the tiles, the bars and the button */
.statbox { border: 1.5px solid var(--ink); border-radius: 7px; background: transparent; overflow: hidden; }
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; margin: 0; border-bottom: 1.5px solid var(--ink); }
.stat { padding: 2.1rem 0.6rem 1.9rem; text-align: center; border-right: 1.5px solid var(--ink-faint); }
.stat:nth-child(2n) { border-right: 0; }
.stat .sk { font-family: var(--mono); font-size: 1rem; letter-spacing: 0.01em; text-transform: uppercase; color: var(--label); margin-bottom: 0.2rem; }
.stat .sv { font-family: var(--head); font-weight: 700; font-size: 3.4rem; line-height: 1; margin: 0.1rem 0 0.5rem; }
.stat .sl { font-family: var(--mono); font-size: 1.05rem; letter-spacing: 0.01em; text-transform: uppercase; color: var(--ink); }
.bars { padding: 1.4rem 1.4rem 1.6rem; }
.bars .bh { font-family: var(--mono); font-size: 1.1rem; letter-spacing: 0.01em; text-transform: uppercase; color: var(--label); margin: 0 0 0.9rem; }
.bar { display: grid; grid-template-columns: 8.6rem 1fr 2.4rem; gap: 0.8rem; align-items: center; margin: 0; padding: 1rem 0; border-bottom: 1.5px solid rgba(30,30,27,0.18); appearance: none; background: none; border-left: 0; border-right: 0; border-top: 0; width: 100%; cursor: pointer; color: inherit; font: inherit; text-align: left; }
.bar .bl { font-family: var(--mono); font-size: 1.05rem; letter-spacing: 0.01em; text-transform: uppercase; }
.bar .bt { height: 0.5rem; background: #E3D9BE; border-radius: 1px; }
.bar .bt i { display: block; height: 100%; background: var(--fg-olive); }
.bar .bn { font-family: var(--mono); font-size: 1.05rem; text-align: right; }
.bars .btn-olive { margin-top: 1.6rem; }
/* Solid buttons are olive INK on paper, same recipe as the FAB: a
   translucent wash over the page's texture, multiply-blended so the grain
   reads through. */
.btn-olive { display: block; width: 100%; margin-top: 1.4rem; padding: 1.3rem;
  font-family: var(--mono); font-size: 1.3rem; font-weight: 500; letter-spacing: 0.01em; text-transform: uppercase;
  color: #F6F1DE;
  /* grain.png carries its texture in the ALPHA channel, so it reads on a
     dark olive. The old recipe multiplied the LIGHT paper tile onto the
     olive, which compressed its variation to ~2 levels out of 255 —
     measurably invisible, which is why these looked flat. */
  background: url('/assets/grain.png') 0 0 / 300px 300px, var(--fg-olive);
  border: 1.5px solid rgba(30, 30, 27, 0.4); border-radius: 8px; cursor: pointer; }
.btn-olive:active { background-color: var(--fg-olive-deep); }

/* On a dark coin tile the worn red stamp disappears. Over the tile it goes
   solid: opaque ink, no wear mask, brighter red, so CARRY actually reads. */
.plate-cell .stamp-corner, .tile .stamp-corner {
  top: 0.5rem; right: 0.5rem; font-size: 0.56rem; letter-spacing: 0.16em; padding: 0.16rem 0.36rem;
  border-width: 2px; z-index: 1;
  color: #FFF1EC; background: #A6402F; border-color: #E7A091; opacity: 1;
  -webkit-mask-image: none; mask-image: none;
  box-shadow: 0 1px 3px rgba(0,0,0,0.5); }

/* ══ POLAROID PRINTS ═════════════════════════════════════════════════════
   Coin photos are physical prints taped to the board: a worn card with a fat
   chin, one hand-torn strip across the top, and a tilt that never repeats.
   Card faces and tape strips are generated (tools/make-polaroid.php,
   tools/make-tape.php) — four of each, cycled at different strides so
   neighbours never match. See CLAUDE.md before changing any of this. */
.pol { position: relative; padding: 0.5rem 0.5rem 0;
  background: var(--card, url('/assets/polaroid-1.png')) 0 0 / 100% 100% no-repeat;
  /* The card's corners are TRANSPARENT in the PNG (they are torn), so this
     has to be drop-shadow — box-shadow would trace the square box instead. */
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.16)) drop-shadow(0 8px 13px rgba(0,0,0,.26));
  transform: rotate(var(--tilt, -1.6deg)); transform-origin: 50% 30%; }
/* grain.png as a plain background layer is tuned for dark olive and reads as
   mould on a white card; as an overlay with its own opacity it is just paper. */
.pol::before { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: url('/assets/grain.png') 0 0 / 300px 300px; opacity: 0.17; mix-blend-mode: multiply; }
.pol .win { display: block; aspect-ratio: 1; background: #191A16; overflow: hidden; position: relative; }
.pol .win img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pol .chin { padding: 0.6rem 0.25rem 0.72rem; text-align: center; position: relative; z-index: 2; }
.pol .cap { display: block; font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: #2A2C24; line-height: 1.3; }
.pol .cap2 { display: block; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: #8A8875; margin-top: 0.22rem; }
/* Tape: multiply so it darkens the board rather than covering it. */
.pol .tape { position: absolute; z-index: 2; top: -0.68rem; left: 50%; height: 1.6rem; width: 4.6rem;
  background: var(--strip, url('/assets/tape-1.png')) 0 0 / 100% 100% no-repeat;
  mix-blend-mode: multiply; filter: drop-shadow(0 1px 1px rgba(0,0,0,.18)); pointer-events: none;
  transform: translateX(-50%) rotate(var(--tape-tilt, -2.5deg)); }
/* Carry is stamped on the CHIN, where the card is pale enough for red ink to
   read. Over the photo it was invisible. inline-block, or it stretches the
   full chin and collides with the line above it. */
.pol .stamp-carry { display: inline-block; margin-top: 0.46rem; font-size: 0.56rem;
  padding: 0.14rem 0.42rem; border-width: 2px; letter-spacing: 0.2em; }

/* Rack tiles are the prints. */
.tile.pol-cell { padding: 0; background: none; }
.tile.pol-cell .sq { aspect-ratio: 1; background: #1E2119; border-radius: 0; padding: 0; }
.tile.pol-cell .sq img { object-fit: cover; filter: none; }
/* A blank coin is artwork, not a photo: it must sit INSIDE the window with
   room around it, not be cropped to fill like a real photo would be. */
.pol .face-blank { background: none; }
.pol .face-blank img { object-fit: contain; padding: 9%; box-sizing: border-box;
  filter: drop-shadow(0 4px 5px rgba(0,0,0,0.55)); }
/* Prints need room for the tape and the tilt; the old tight gutter clipped both. */
.tiles.tiles-pol { gap: 2.4rem 1.5rem; padding: 0.5rem 0.2rem 0; }

/* The detail hero is the same print, bigger. */
.hero-pol { width: 15.5rem; margin: 0 auto; touch-action: pan-y; -webkit-user-select: none; user-select: none; }
/* .hero still carries its old fixed 15.5rem box; inside a padded card that
   overflows the print by the padding on each side. */
.hero-pol .hero { width: 100%; height: auto; display: block; }
.hero-pol .win { cursor: pointer; }
.hero-pol .chin { padding: 0.68rem 0.25rem 0.8rem; }

/* Carry on the detail page: the wide stamp, sitting between the face dots and
   the coin's name. The chin treatment used on rack prints has no room here. */
.carry-bar { text-align: center; margin: 0.2rem 0 1.1rem; }
.stamp-wide { display: inline-block; font-size: 0.72rem; letter-spacing: 0.38em;
  padding: 0.34rem 2.6rem 0.34rem 2.98rem; border-width: 2.5px; transform: rotate(-1.6deg); }

/* ── The story ───────────────────────────────────────────────────────────
   The provenance is the product. As a table row between Unit and Serial it
   read as one more field to fill in, so it gets its own block, set as prose
   at a size meant for reading rather than scanning. */
.story { margin: 1.9rem 0 0.6rem; }
.story h4 { font-family: var(--head); font-weight: 500; font-size: 1.14rem; letter-spacing: 0.05em;
  text-transform: uppercase; margin: 0 0 0.75rem; color: var(--ink); }
.story-body { font-family: var(--mono); font-size: 1.02rem; line-height: 1.72; color: var(--ink);
  margin: 0; white-space: pre-wrap; }
.story-prompt { color: var(--ink-soft); }
.story-btn { margin-top: 1.1rem; }

/* ── Account screen ──────────────────────────────────────────────────────
   Profile and Settings were one screen split in two — General and Sharing
   each opened the SAME sheet from both sides. Merged, it needs grouping to
   stay readable. */
.acct { margin-top: 1.1rem; }
.acct-head { margin: 1.8rem 0 0.5rem; }
.acct .settings + .settings { margin-top: 1.6rem; }

/* The tip jar as a card, not a menu row buried at the bottom of one. */
.tipcard { border: 1.5px solid var(--ink); border-radius: 7px; padding: 1.15rem 1.2rem 1.25rem;
  margin: 1.9rem 0 0.4rem; background: transparent; }
.tipcard .pl { margin: 0 0 0.5rem; }
.tc-body { font-family: var(--mono); font-size: 0.97rem; line-height: 1.6; color: var(--ink-soft); margin: 0 0 1.1rem; }
.tc-btn { width: 100%; }

/* A sheet at the bottom of the stack CLOSES; the panel travels down, so a back
   chevron is the wrong metaphor and stacks a second '‹' under the screen's own.
   Only a sheet opened from a sheet keeps the back arrow. */
.sheet-close { font-size: 1.85rem; line-height: 1; font-weight: 400; }

/* ── Field manual, in-app ────────────────────────────────────────────────
   The same content /manual serves, set for a phone sheet rather than a page. */
.mn-lede { font-family: var(--mono); font-size: 1rem; line-height: 1.6; color: var(--ink-soft); margin: 0 0 1.4rem; }
.mn-h { font-family: var(--head); font-weight: 500; font-size: 1.1rem; letter-spacing: 0.05em;
  text-transform: uppercase; margin: 1.9rem 0 0.7rem; }
.mn-p { font-family: var(--mono); font-size: 1rem; line-height: 1.68; margin: 0 0 1rem; }
.mn-dim { color: var(--ink-soft); margin-top: -0.35rem; }
.mn-note { border: 1.5px solid var(--ink); border-radius: 7px; padding: 1rem 1.05rem; margin: 1.5rem 0; }
.mn-note p { font-family: var(--mono); font-size: 0.97rem; line-height: 1.62; margin: 0; color: var(--ink-soft); }
.mn-steps { list-style: none; margin: 0.4rem 0 1.2rem; padding: 0; counter-reset: mnstep; }
.mn-steps li { counter-increment: mnstep; position: relative; padding: 0 0 1.15rem 2.9rem; }
.mn-steps li::before { content: counter(mnstep, decimal-leading-zero); position: absolute; left: 0; top: 0.1rem;
  font-family: var(--mono); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.08em; color: var(--label);
  border: 1.5px solid var(--ink-faint); border-radius: 4px; padding: 0.1rem 0.34rem; }
.mn-steps b { display: block; font-family: var(--mono); font-size: 0.95rem; letter-spacing: 0.03em;
  text-transform: uppercase; margin-bottom: 0.22rem; }
.mn-steps span { font-family: var(--mono); font-size: 0.97rem; line-height: 1.6; color: var(--ink-soft); }

/* A gear row is the whole target, and it names where it goes — the web page
   learned the same lesson: the product name alone is only findable by hover. */
.gear-row { display: grid; grid-template-columns: 3.6rem 1fr; gap: 1rem; align-items: start;
  text-decoration: none; color: inherit; padding: 1.1rem 0.9rem; margin: 0 -0.9rem;
  border-bottom: 1.5px dotted var(--ink-faint); border-radius: 7px; }
.gr-thumb { display: block; width: 3.6rem; height: 3.6rem; border: 1.5px solid var(--ink-faint);
  border-radius: 4px; overflow: hidden; }
.gr-thumb img { width: 100%; height: 100%; display: block; object-fit: cover; }
.gr-body { display: block; min-width: 0; }
.gear-row:last-of-type { border-bottom: 0; }
.gear-row:active { background: rgba(30, 30, 27, 0.05); }
.gr-top { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.gr-name { font-family: var(--mono); font-weight: 700; font-size: 1rem; letter-spacing: 0.03em; text-transform: uppercase; }
.gr-price { font-family: var(--mono); font-size: 0.8rem; letter-spacing: 0.08em; color: var(--label); white-space: nowrap; }
.gr-blurb { display: block; font-family: var(--mono); font-size: 0.95rem; line-height: 1.58; color: var(--ink-soft); margin-top: 0.4rem; }
.gr-go { display: block; font-family: var(--mono); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--od); margin-top: 0.7rem; }

/* A settings row carrying a title AND a caption. The title must be the SAME
   type as every other .srow in the app — mono 1.45rem, sentence case. It was
   briefly var(--head) uppercase here, which made the Manual tab read as a
   different app from Profile. The caption is the only addition. */
.srow .st .mt { font-family: var(--mono); font-size: 1.45rem; line-height: 1.25;
  letter-spacing: 0; text-transform: none; }
.srow .st .ms { font-family: var(--mono); font-size: 0.95rem; line-height: 1.45; color: var(--ink-soft);
  margin-top: 0.3rem; text-transform: none; letter-spacing: 0; }

/* A section band. The gear sheet ran four sections of bold-then-body, and at a
   glance every heading looked like one more product name. Olive, so a break
   is a break — same tape/webbing family as the bars. */
.mn-band { background: url('/assets/grain.png') 0 0 / 560px 560px, var(--fg-olive);
  border-radius: 7px; padding: 0.72rem 0.9rem 0.8rem; margin: 2.2rem -0.15rem 1.1rem; }
.mn-band h4 { font-family: var(--head); font-weight: 500; font-size: 1.04rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: #F4F0DE; margin: 0; text-shadow: 0 1px 1px rgba(0,0,0,0.35); }
.mn-band p { font-family: var(--mono); font-size: 0.9rem; line-height: 1.5; color: rgba(244, 240, 222, 0.78);
  margin: 0.25rem 0 0; }

/* ── Tip tiers on the web ────────────────────────────────────────────────
   The same three amounts the app offers. Picking one slides down the two
   ways to send it: the amount is the decision, the service is a detail. */
.tip-tier { display: block; }
.tip-tier + .tip-tier { margin-top: 0.7rem; }
.tip-tier .tip-btn { width: 100%; }
.tip-tier.open .tip-btn { background: rgba(62, 74, 51, 0.10); }
.tip-pay { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem;
  max-height: 0; opacity: 0; overflow: hidden; margin-top: 0;
  transition: max-height 260ms cubic-bezier(.32,.72,0,1), opacity 180ms ease, margin-top 260ms ease; }
.tip-tier.open .tip-pay { max-height: 6rem; opacity: 1; margin-top: 0.6rem; }
@media (prefers-reduced-motion: reduce) { .tip-pay { transition: none; } }
.tip-pay-btn { width: 100%; text-align: center; }
