/* ---- design tokens (the offl1ne house style, amethyst accent) -------- */
:root {
  --bg: #f7f5f9;
  --surface: #ffffff;
  --surface-2: #efecf3;
  --border: #e4e0ea;
  --ink: #1b1823;
  --muted: #6f6a7d;
  --accent: #6d4a9c;
  --accent-hover: #5d3e87;
  --accent-ink: #ffffff;
  --accent-weak: rgba(109, 74, 156, .12);
  --pos: #2f6b46;
  --neg: #b23b2e;
  --warn-bg: #f6e9c9;
  --warn-ink: #7a4f05;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.05);
  --shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.07);
  --radius: 16px;
  --radius-sm: 11px;
  --bar: rgba(255,255,255,.78);
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #171520;
    --surface: #221f2c;
    --surface-2: #2b2836;
    --border: #383345;
    --ink: #efecf4;
    --muted: #a09aae;
    --accent: #b28ce0;
    --accent-hover: #c6a6ee;
    --accent-ink: #1a1226;
    --accent-weak: rgba(178, 140, 224, .16);
    --pos: #6fcf97;
    --neg: #f08b7e;
    --warn-bg: #3a3320;
    --warn-ink: #f0d68a;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.3);
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 10px 30px rgba(0,0,0,.45);
    --bar: rgba(23,21,32,.72);
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font: 16px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); }
h1 { letter-spacing: -.02em; font-size: 1.5rem; margin: .2rem 0 .4rem; }
h2 { margin: 0 0 .2rem; font-size: 1rem; }
img { max-width: 100%; }

/* ---- top bar -------------------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .7rem clamp(1rem, 4vw, 1.5rem);
  padding-top: max(.7rem, env(safe-area-inset-top));
  background: var(--bar);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border);
}
.brand {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--ink); font-weight: 700; font-size: 1.08rem;
  text-decoration: none; letter-spacing: -.01em;
}
.brand::before { content: ""; display: inline-block; width: 1.5em; height: 1.5em;
  vertical-align: -.35em; background: url("icons/icon.svg") center/contain no-repeat; }

/* ---- burger menu (collections + account) ----------------------------
   A checkbox toggle, no JavaScript — same technique as the retired cross-app
   burger in shared/nav.php. That one was dropped because switching APPS crosses
   a subdomain and knocks an installed PWA out of standalone; this one only links
   within stones, so it keeps its keep. */
.burger-toggle { position: absolute; opacity: 0; pointer-events: none; }
.burger {
  width: 2.6rem; height: 2.6rem; flex: none; cursor: pointer;
  display: grid; place-items: center; border-radius: 999px;
  -webkit-tap-highlight-color: transparent;
}
.burger:hover { background: var(--surface-2); }
/* Three bars drawn from one element: the middle is the box, the outer two are
   its ::before/::after. */
.burger span, .burger span::before, .burger span::after {
  content: ""; display: block; width: 20px; height: 2px; border-radius: 2px;
  background: var(--ink); transition: transform .18s ease, opacity .18s ease;
}
.burger span { position: relative; }
.burger span::before { position: absolute; top: -6px; }
.burger span::after  { position: absolute; top:  6px; }
.burger-toggle:checked ~ .topbar .burger span { background: transparent; }
.burger-toggle:checked ~ .topbar .burger span::before { transform: translateY(6px) rotate(45deg); }
.burger-toggle:checked ~ .topbar .burger span::after  { transform: translateY(-6px) rotate(-45deg); }

/* Viewport-sized clip layer. The closed panel is parked one panel-width off the
   right edge; without something to clip it, that parked box adds its own width
   to the document's horizontal scroll extent on every page. */
/* z-index 28 beats .topbar (20) and .fab (25). This only works because the
   wrapper is a sibling of the bar: as a descendant it would have been trapped in
   the bar's stacking context AND in its containing block. */
.menu-wrap {
  position: fixed; inset: 0; z-index: 28; overflow: hidden;
  visibility: hidden; pointer-events: none;
}
.burger-toggle:checked ~ .menu-wrap { visibility: visible; pointer-events: auto; }

/* Tapping anywhere outside closes it. */
.burger-scrim { position: absolute; inset: 0; background: rgba(0,0,0,.35);
  opacity: 0; transition: opacity .18s ease; }
.burger-toggle:checked ~ .menu-wrap .burger-scrim { opacity: 1; }

.menu {
  position: absolute; top: 0; right: 0; height: 100%;
  width: min(19rem, 84vw);
  padding: max(1rem, env(safe-area-inset-top)) 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
  background: var(--surface); border-left: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: .15rem; overflow-y: auto;
  transform: translateX(100%); transition: transform .2s ease;
}
/* visibility on the wrapper keeps the closed menu out of the tab order and out
   of the accessibility tree, not just off-screen. */
.burger-toggle:checked ~ .menu-wrap .menu { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .menu, .burger-scrim, .burger span, .burger span::before, .burger span::after { transition: none; }
}
.menu h2 {
  margin: 1.1rem 0 .4rem; font-size: .7rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
  padding: 0 .7rem;
}
.mgroup { display: flex; flex-direction: column; gap: .15rem; }

.menu .ci {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .6rem .7rem; border-radius: var(--radius-sm);
  color: var(--ink); text-decoration: none; font-size: .95rem;
}
.menu .ci:hover { background: var(--surface-2); }
.menu .ci.on { background: var(--accent-weak); color: var(--accent); font-weight: 600; }
/* One line per entry: the panel is only 19rem wide and a wrapped owner name made
   the rows uneven and hard to scan. The name truncates, the count never does. */
.menu .cn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu .cn em { font-style: normal; color: var(--muted); font-size: .8em; }
.menu .cc { flex: none; color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums;
  text-align: right; line-height: 1.25; }
.menu .cs { display: block; font-size: .92em; opacity: .8; }

/* Default buckets ("All pieces", "Unfiled") are views the app always provides,
   not collections anyone made — nobody can rename or delete them. They read as
   one filled control block at the top, distinct from the list below. */
.mgroup.defaults {
  gap: 0; background: var(--surface-2); border-radius: var(--radius-sm);
  padding: .2rem; margin-bottom: .2rem;
}
.mgroup.defaults .ci.def { font-weight: 600; }
.mgroup.defaults .ci.def:hover { background: var(--surface); }
.mgroup.defaults .ci.def.on { background: var(--surface); color: var(--accent); }
/* Hairline between the two buckets, drawn only when there are two. */
.mgroup.defaults .ci.def + .ci.def { box-shadow: 0 -1px 0 var(--border); }

/* A user's collection carries an accent tick, so the eye can tell "somebody made
   this" from "the app provides this" without reading the labels. */
.menu .ci.own { padding-left: 1.4rem; position: relative; }
.menu .ci.own::before {
  content: ""; position: absolute; left: .6rem; top: 50%; transform: translateY(-50%);
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
  opacity: .55;
}
.menu .ci.own.on::before { opacity: 1; }

.mempty { margin: .1rem 0 0; padding: .2rem .7rem .4rem; color: var(--muted); font-size: .85rem; }

.mfoot {
  margin-top: auto; padding-top: .7rem; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: .15rem;
}
.menu .manage, .menu .out { color: var(--muted); font-size: .9rem; }

main {
  max-width: 760px; margin: 0 auto; padding: clamp(1rem, 4vw, 1.6rem);
  /* Room for the floating add button so it never covers the last row. */
  padding-bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
}

/* ---- forms / cards -------------------------------------------------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.1rem;
  display: flex; flex-direction: column; gap: .8rem;
  box-shadow: var(--shadow-sm);
}
.stack { display: flex; flex-direction: column; gap: .9rem; }
label { display: flex; flex-direction: column; gap: .3rem; font-size: .8rem; font-weight: 500; color: var(--muted); }
label .hint { font-weight: 400; opacity: .75; }
input, select, textarea {
  /* 16px keeps iOS Safari from auto-zooming the viewport on focus. These controls
     sit inside <label> (.8rem), so an inherited size would be ~12.8px and trigger
     the zoom. */
  font-family: inherit; font-size: 16px; color: var(--ink); width: 100%;
  padding: .6rem .7rem; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface);
}
textarea { min-height: 5rem; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak);
}
input:disabled, select:disabled { background: var(--surface-2); color: var(--muted); }
/* Field + button on one line (the "New collection" form). This rule is what
   class="row" in the markup expects; without it the form falls back to a plain
   block and the button sits flush against the input above it. */
.row { display: flex; gap: .6rem; align-items: flex-end; }
.row > input, .row > select { flex: 1; min-width: 0; }
/* Below ~24rem the pair no longer fits side by side; stack it and restore the
   vertical gap rather than letting the button crowd the field. */
@media (max-width: 24rem) { .row { flex-direction: column; align-items: stretch; gap: .7rem; } }

.pair { display: flex; gap: .8rem; }
.pair > label { flex: 1; min-width: 0; }
.pair > label > input, .pair > label > select { min-width: 0; }

/* Dates stack until there is genuinely room for two of them.
   input[type=date] has a UA-enforced INTRINSIC minimum width — it renders the
   formatted date and refuses to shrink below it, ignoring width:100% and
   min-width:0. Two side by side therefore overflow their flex tracks and
   visually collide, and a long locale format ("1. Aug 2026") makes it worse.
   Below 34rem there is one control per row, so an overlap is impossible by
   construction rather than by a width guess that a different locale can break. */
.pair.dates { flex-direction: column; gap: .9rem; }
@media (min-width: 34rem) {
  .pair.dates { flex-direction: row; gap: .8rem; }
}
/* The two captions are one line each (see the .cap wrapper in item_edit.php), so
   the controls already line up. margin-top:auto is the safety net: .pair stretches
   both labels to the same height, so if a caption ever wraps on a narrow screen
   (the Paid/Value pair carries a hint on BOTH sides) the controls still sit on a
   shared baseline instead of stepping. */
.pair > label > .cap { display: block; }
.pair > label > select, .pair > label > .cap + input { margin-top: auto; }
/* Below ~360px the two side-by-side selects truncate their own option text
   (a native select won't shrink its font), so stack them instead. */
@media (max-width: 22.5rem) { .pair { flex-direction: column; gap: .9rem; } }

button, .btn {
  font: inherit; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  border: 1px solid transparent; border-radius: 999px;
  padding: .55rem 1.1rem; background: var(--surface-2); color: var(--ink);
  text-decoration: none;
}
button:active, .btn:active { transform: translateY(1px); }
button.primary, .btn.primary { background: var(--accent); color: var(--accent-ink); }
button.primary:hover, .btn.primary:hover { background: var(--accent-hover); }
.btn.danger, button.danger { background: transparent; color: var(--neg); border-color: var(--border); }
.btn.tiny { padding: .25rem .6rem; font-size: .78rem; }
.actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .4rem; }

/* ---- filter bar ----------------------------------------------------- */
.filters { display: flex; flex-direction: column; gap: .6rem; margin-bottom: .8rem; }
.searchrow { display: flex; gap: .6rem; align-items: stretch; }
.search { position: relative; flex: 1; display: flex; }
.search input { padding-right: 2.2rem; }
.search .clear {
  position: absolute; right: .5rem; top: 50%; transform: translateY(-50%);
  width: 1.6rem; height: 1.6rem; display: grid; place-items: center;
  border-radius: 50%; background: var(--surface-2); color: var(--muted);
  text-decoration: none; font-size: 1rem; line-height: 1;
}
.searchrow .go { flex: none; }

.more { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
.more > summary {
  cursor: pointer; list-style: none; padding: .55rem .9rem;
  font-size: .9rem; font-weight: 600; color: var(--accent);
  display: flex; align-items: center; gap: .4rem;
}
.more > summary::-webkit-details-marker { display: none; }
.more > summary::before { content: "▸"; font-size: .8em; }
.more[open] > summary::before { content: "▾"; }
.more .dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--accent); display: inline-block; }
.more .grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .7rem; padding: .2rem .9rem .9rem;
}
.more .filteractions { display: flex; gap: .6rem; padding: 0 .9rem .9rem; }

.count { color: var(--muted); font-size: .85rem; margin: .2rem 0 .8rem; }
/* Worth minus paid. The sign carries the meaning on its own (and must, for
   anyone who can't separate the two hues), so --pos/--neg only reinforce it. */
.delta { font-weight: 600; }
/* Statistics. Value and Paid are sums over overlapping but different sets of
   pieces, so the delta never sits in this row as a third column — a reader
   subtracts two adjacent money figures, and Value − Paid is not the delta. It
   gets .deltaline below, carrying the subtotals it was actually computed from. */
.statcard { padding: .9rem 1rem 1rem; }
.statcard h2, .statcard h3 { margin: 0 0 .7rem; font-size: 1rem; }
.statcard h3 em { font-style: normal; font-weight: 500; color: var(--muted); font-size: .8rem; }
.statcard.total { border: 1px solid var(--accent-weak); }
/* Label left, figure right, one per row — and only three abreast once there is
   genuinely room, the same rule .pair.dates follows. Three money figures side by
   side is the same mistake as two date inputs: "€22,860.00" at 1.15rem will not
   shrink, so on a 320px phone the three tracks overflowed the card by 20px.
   Measured, not guessed. */
.statgrid { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .45rem; }
.statgrid > li { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 0 .6rem; }
.sl { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sv { font-size: 1.05rem; font-weight: 700; text-align: right; }
/* The caveat counts wrap rather than truncate: a number whose basis is cut off
   mid-phrase is worse than a taller card. */
.sn { font-size: .74rem; color: var(--muted); line-height: 1.25; }
.statgrid .sn { grid-column: 2; text-align: right; }
@media (min-width: 34rem) {
  .statgrid { flex-direction: row; gap: .7rem; }
  .statgrid > li { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
  .sv { font-size: 1.15rem; text-align: left; }
  .statgrid .sn { text-align: left; }
}
.deltaline { margin: .7rem 0 0; padding-top: .6rem; border-top: 1px solid var(--border); font-size: .85rem; }
/* Which set of pieces a delta is about. Only meaningful because there are two
   of them — still-owned and sold — sitting one above the other. */
.dlabel { color: var(--muted); font-size: .74rem; text-transform: uppercase;
  letter-spacing: .04em; margin-right: .45rem; }
/* A second delta directly under the first reads as one block, not two. */
.deltaline + .deltaline { margin-top: .45rem; padding-top: .45rem; border-top: 0; }
.deltaline .sn { display: block; margin-top: .1rem; }
.goldline { border-top-style: dashed; }
.pricenote { margin-top: .8rem; }
.sechead { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 1.4rem 0 .6rem; }
.note { font-size: .8rem; margin-top: 1.2rem; }
.delta.up { color: var(--pos); }
.delta.down { color: var(--neg); }

/* ---- collection groups + the sold sub-collection --------------------- */
.scope { margin: .1rem 0 .1rem; }
.scope em { font-style: normal; color: var(--muted); font-size: .6em; font-weight: 500; }
.group { margin: 0 0 1.4rem; }
.grouphead {
  display: flex; align-items: baseline; justify-content: space-between; gap: .8rem;
  margin: 0 0 .5rem; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--border); padding-bottom: .35rem;
}
.groupmeta { flex: none; font-weight: 600; letter-spacing: 0; text-transform: none; }

/* Sold pieces stay visible but read as no longer part of what is owned: the
   whole block is dimmed and desaturated, and lifts on hover so it is still
   usable rather than merely decorative. */
.muted-group { opacity: .58; }
.muted-group:hover, .muted-group:focus-within { opacity: 1; }
.muted-group .item .shot img { filter: grayscale(1); }
.muted-group .item:hover .shot img { filter: none; }
.soldtag {
  display: block; font-weight: 500; font-size: .92em; color: var(--muted);
}
.soldbadge {
  font-size: .5em; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  vertical-align: middle; margin-left: .5rem; padding: .2rem .5rem; border-radius: 999px;
  background: var(--surface-2); color: var(--muted);
}
.value-big.is-sold { color: var(--muted); }

/* ---- collections page ------------------------------------------------ */
.collist { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: .7rem; }
.crow { display: flex; gap: .6rem; }
.crow input { flex: 1; }
.cmeta { margin: 0; font-size: .85rem; }
.deftag {
  display: inline-block; margin-left: .35rem; padding: .05rem .4rem; border-radius: 999px;
  background: var(--accent-weak); color: var(--accent);
  font-size: .68rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}
.crowbtns { display: flex; flex-wrap: wrap; gap: .5rem; }

/* ---- catalogue grid ------------------------------------------------- */
.items {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem;
}
@media (min-width: 34rem) { .items { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 50rem) { .items { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.item { position: relative; }
.item > a {
  display: flex; flex-direction: column; height: 100%;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
  text-decoration: none; color: var(--ink); box-shadow: var(--shadow-sm);
}
.item .shot { position: relative; display: block; aspect-ratio: 1 / 1; background: var(--surface-2); }
.item .shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.item .noshot {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 2rem; color: var(--border);
}
.item .shots, .item .gems {
  position: absolute; bottom: .4rem; font-size: .7rem; font-weight: 600;
  padding: .1rem .4rem; border-radius: 999px;
  background: rgba(0,0,0,.55); color: #fff;
}
.item .shots { right: .4rem; }
.item .gems { left: .4rem; bottom: auto; top: .4rem; background: var(--accent); color: var(--accent-ink); }
.item .meta { display: flex; flex-direction: column; gap: .1rem; padding: .6rem .7rem .7rem; }
.item .t { font-weight: 600; font-size: .92rem; line-height: 1.3; }
.item .s { font-size: .75rem; color: var(--muted); }
.item .v { font-size: .8rem; font-weight: 600; margin-top: .15rem; }

.fab {
  position: fixed; right: 1.1rem; z-index: 25;
  bottom: calc(1.1rem + env(safe-area-inset-bottom, 0px));
  width: 3.4rem; height: 3.4rem; border-radius: 50%;
  display: grid; place-items: center; font-size: 1.9rem; line-height: 1;
  background: var(--accent); color: var(--accent-ink);
  text-decoration: none; box-shadow: var(--shadow);
}

/* ---- detail page ---------------------------------------------------- */
.crumb { margin: 0 0 .6rem; font-size: .9rem; }
.crumb a { text-decoration: none; }

.gallery { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; gap: .6rem; }
.gallery.multi {
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.gallery.multi::-webkit-scrollbar { display: none; }
.gallery li { flex: none; scroll-snap-align: center; }
.gallery li img {
  width: 100%; max-width: 100%; height: auto; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface-2); display: block;
}
.gallery.multi li { width: min(84%, 26rem); }
.gallery:not(.multi) li { width: 100%; }

.value-big { font-size: 1.7rem; font-weight: 700; margin: 0 0 .8rem; color: var(--accent); }

.facts { display: grid; grid-template-columns: 8rem 1fr; gap: .35rem .8rem; margin: 0 0 1.2rem; }
.facts dt { font-size: .8rem; color: var(--muted); }
.facts dd { margin: 0; font-size: .95rem; }
.notes p { margin: 0; }
.added { margin: 1.2rem 0 .6rem; font-size: .82rem; }

/* ---- edit form ------------------------------------------------------ */
.editform .card h2 { color: var(--muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; }
.stonerows { display: flex; flex-direction: column; gap: .5rem; }
.stonerow { display: flex; gap: .5rem; }
.stonerow input[type="text"] { flex: 2; }
.stonerow input[type="number"] { flex: 1; min-width: 5.5rem; }
.addstone { align-self: flex-start; }

.filepick input[type="file"] { font-size: .9rem; padding: .5rem; }
.picks { list-style: none; margin: .4rem 0 0; padding: 0; display: flex; gap: .5rem; flex-wrap: wrap; }
.picks li { width: 4.5rem; height: 4.5rem; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--border); }
.picks img { width: 100%; height: 100%; object-fit: cover; }

.gallery.edit { flex-wrap: wrap; }
.gallery.edit li { position: relative; width: calc(50% - .3rem); }
.gallery.edit img { aspect-ratio: 1 / 1; object-fit: cover; }
.gallery.edit .badge {
  position: absolute; top: .4rem; left: .4rem; font-size: .68rem; font-weight: 700;
  padding: .1rem .45rem; border-radius: 999px; background: var(--accent); color: var(--accent-ink);
}
.gallery.edit .imgactions {
  position: absolute; left: .4rem; right: .4rem; bottom: .4rem;
  display: flex; gap: .3rem; justify-content: center; flex-wrap: wrap;
}
.gallery.edit .imgactions .btn { background: rgba(255,255,255,.92); color: #1b1823; border-color: transparent; }
.gallery.edit .imgactions .btn.danger { color: #b23b2e; }

.hiddenform { display: none; }
.danger-zone { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); }

/* ---- misc ----------------------------------------------------------- */
.flash { background: var(--warn-bg); color: var(--warn-ink); border-radius: var(--radius-sm);
  padding: .6rem .9rem; margin: 0 0 1rem; font-size: .92rem; }
.empty { color: var(--muted); padding: 2rem 0; text-align: center; }
.muted { color: var(--muted); font-size: .9rem; }
