/**
 * app.css — components and layout.
 *
 * Rules for the next agent:
 *  1. No raw colour values. Every colour resolves through a token in tokens.css.
 *  2. Mobile is the base case. Media queries only ever *add* for wider screens.
 *  3. Simple mode hides via [data-mode="simple"] .adv-only — never by deleting
 *     nodes, so switching modes costs no re-render.
 */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--bg);
  overflow-wrap: break-word;
  /* Paper grain. An inline SVG turbulence keeps the warmth of the seed-catalogue
     look without shipping a texture file or breaking the `img-src 'self' data:` CSP. */
  background-image:
    radial-gradient(1200px 600px at 12% -8%, color-mix(in oklab, var(--leaf) 7%, transparent), transparent 70%),
    radial-gradient(900px 500px at 96% 4%, color-mix(in oklab, var(--accent) 7%, transparent), transparent 70%);
  background-attachment: fixed;
  min-height: 100dvh;
}
h1, h2, h3, h4 { font-family: var(--font-display); line-height: var(--lh-tight); margin: 0; font-weight: 600; }
p { margin: 0 0 var(--s3); }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
img, svg { max-width: 100%; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
::selection { background: color-mix(in oklab, var(--accent) 26%, transparent); }

/* Scrollbars, so the desktop build doesn't look like a default web page. */
* { scrollbar-width: thin; scrollbar-color: var(--hairline-2) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--hairline-2); border-radius: var(--r-pill); border: 3px solid transparent; background-clip: content-box; }

/* Base size for every icon() SVG. Container rules (.btn svg, .tab svg, ...)
   are more specific and override it where a fixed pixel size is wanted. */
.ico { width: 1.15em; height: 1.15em; flex: none; vertical-align: -0.18em; }

/* The UA sheet's `[hidden] { display: none }` loses to any author rule that
   sets display, which is every component class here. Views legitimately use
   the hidden attribute, so make it win. */
[hidden] { display: none !important; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip-link {
  position: fixed; top: -100px; left: var(--s3); z-index: 200;
  background: var(--accent); color: var(--accent-ink);
  padding: var(--s2) var(--s4); border-radius: var(--r-sm); transition: top var(--dur-2) var(--ease);
}
.skip-link:focus { top: calc(var(--safe-t) + var(--s3)); }

/* ============================ App frame ================================ */

#app { display: flex; flex-direction: column; min-height: 100dvh; }

.topbar {
  position: sticky; top: 0; z-index: 60;
  padding-top: var(--safe-t);
  background: color-mix(in oklab, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--hairline);
}
.topbar__row {
  height: var(--header-h); display: flex; align-items: center; gap: var(--s3);
  max-width: var(--page-max); margin: 0 auto; padding: 0 var(--s4);
}
.brandmark { display: flex; align-items: center; gap: var(--s2); min-width: 0; text-decoration: none; color: inherit; }
.brandmark__sigil {
  width: 2rem; height: 2rem; flex: none; display: grid; place-items: center;
  font-size: 1.05rem; border-radius: var(--r-sm);
  background: linear-gradient(145deg, var(--accent-soft), var(--leaf-soft));
  border: 1px solid var(--hairline);
}
.brandmark__name {
  font-family: var(--font-display); font-size: var(--t-md); font-weight: 600;
  letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar__spacer { flex: 1 1 auto; }

/* Bottom padding must clear the tab bar. It is position:sticky, so while the
   page is mid-scroll it overlays whatever is beneath it — without this the last
   row of the glossary is permanently untappable. */
.main { flex: 1 1 auto; width: 100%; max-width: var(--page-max); margin: 0 auto;
  padding: var(--s4) var(--s4) calc(var(--nav-h) + var(--safe-b) + var(--s5)); }
@media (min-width: 900px) { .main { padding-bottom: var(--s7); } }

/* ---- Bottom tab bar: the primary navigation on a phone. ---------------- */
.tabbar {
  position: sticky; bottom: 0; z-index: 60;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  padding: var(--s1) var(--s2) calc(var(--s1) + var(--safe-b));
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--hairline);
}
.tab {
  display: grid; justify-items: center; gap: 2px; padding: var(--s2) var(--s1) var(--s1);
  background: none; border: 0; cursor: pointer; color: var(--ink-3);
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.02em;
  border-radius: var(--r-md); text-decoration: none;
  transition: color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.tab svg { width: 22px; height: 22px; stroke-width: 1.6; }
.tab[aria-current="page"] { color: var(--accent); }
.tab[aria-current="page"] .tab__ico { background: var(--accent-soft); }
.tab__ico { padding: 3px 12px; border-radius: var(--r-pill); transition: background var(--dur-2) var(--ease); }
@media (hover: hover) { .tab:hover { color: var(--ink); } }

@media (min-width: 900px) {
  /* On a wide screen the tab bar becomes a rail under the header — same markup.
     It is a SIBLING AFTER <main> in the DOM (which is what puts it under the
     thumb on a phone), so flex order is what lifts it above the content here.
     Reparenting would need JS; ordering is free. */
  #app { display: flex; flex-direction: column; }
  .topbar { order: 0; }
  .tabbar { order: 1; }
  .main   { order: 2; }
  .tabbar {
    position: sticky; top: var(--header-h); z-index: 55;
    border: 0; border-bottom: 1px solid var(--hairline);
    background: color-mix(in oklab, var(--bg) 86%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    grid-auto-columns: auto; justify-content: center; gap: var(--s1);
    padding: var(--s2) 0;
  }
  .tab { grid-auto-flow: column; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); font-size: var(--t-sm); }
  .tab__ico { padding: 0; background: none !important; }
  .tab[aria-current="page"] { background: var(--accent-soft); }
}

/* ============================ Primitives =============================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 2.75rem; padding: 0 var(--s4);
  border-radius: var(--r-pill); border: 1px solid var(--hairline-2);
  background: var(--surface); color: var(--ink);
  font-size: var(--t-sm); font-weight: 600; cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--sh-1);
  transition: transform var(--dur-1) var(--ease), box-shadow var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(0.97); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }
@media (hover: hover) { .btn:hover:not([disabled]) { box-shadow: var(--sh-2); border-color: var(--hairline-2); } }
.btn--primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.btn--leaf    { background: var(--leaf); color: var(--accent-ink); border-color: transparent; }
.btn--ghost   { background: transparent; box-shadow: none; border-color: var(--hairline); }
.btn--danger  { background: var(--danger-soft); color: var(--danger); border-color: var(--danger); }
.btn--sm { min-height: 2.1rem; padding: 0 var(--s3); font-size: var(--t-xs); }
.btn--block { width: 100%; }
.btn--icon { min-height: 2.5rem; width: 2.5rem; padding: 0; }
.btn svg { width: 18px; height: 18px; stroke-width: 1.8; }

.field { display: grid; gap: var(--s2); margin-bottom: var(--s4); }
.field__label { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--ink-3); }
.field__hint  { font-size: var(--t-xs); color: var(--ink-3); }
.input, .select, .textarea {
  width: 100%; min-height: 2.75rem; padding: var(--s2) var(--s3);
  background: var(--surface); border: 1px solid var(--hairline-2);
  border-radius: var(--r-md); box-shadow: var(--sh-1) inset;
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.textarea { min-height: 8rem; resize: vertical; line-height: var(--lh-body); }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--sh-glow); }
.select { appearance: none; padding-right: var(--s6);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.15rem center, right 0.85rem center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }

.card {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--sh-1);
}
.card--pad { padding: var(--s4); }

.chip {
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: 3px var(--s3); border-radius: var(--r-pill);
  background: var(--surface-3); color: var(--ink-2);
  font-size: var(--t-xs); font-weight: 600; white-space: nowrap;
  border: 1px solid transparent;
}
/* Icons inside chips need an explicit size: nothing else in the cascade
   constrains them, and an unsized 24px SVG renders as a full-width square.
   glossary.mjs (filter/heart/clear) and plant.mjs (toxicity warning) both
   rely on this. */
.chip svg, .fchip svg { width: 15px; height: 15px; flex: none; stroke-width: 1.9; }
.chip--accent { background: var(--accent-soft); color: var(--accent); }
.chip--leaf   { background: var(--leaf-soft); color: var(--leaf); }
.chip--warn   { background: var(--warn-soft); color: var(--warn); }
.chip--danger { background: var(--danger-soft); color: var(--danger); }
.chip-row { display: flex; flex-wrap: wrap; gap: var(--s2); }

.stack   { display: grid; gap: var(--s4); }
.stack-2 { display: grid; gap: var(--s2); }
.row     { display: flex; align-items: center; gap: var(--s3); }
.row--wrap { flex-wrap: wrap; }
.push    { margin-left: auto; }

/* Type-size utilities. Used by plant.mjs and ui.mjs's empty(); they were
   referenced before they existed, which silently rendered at body size. */
.t-xs { font-size: var(--t-xs); }
.t-sm { font-size: var(--t-sm); }
.t-md { font-size: var(--t-md); }

.eyebrow {
  font-size: var(--t-xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: var(--track-caps); color: var(--ink-3);
}
.muted { color: var(--ink-3); }
.num { font-variant-numeric: tabular-nums; }

.section-head { display: flex; align-items: baseline; gap: var(--s3); margin: var(--s6) 0 var(--s3); }
.section-head:first-child { margin-top: 0; }
.section-head h2 { font-size: var(--t-lg); }

.empty { text-align: center; padding: var(--s7) var(--s4); color: var(--ink-3); }
.empty__art { width: 92px; margin: 0 auto var(--s4); opacity: 0.65; }

/* ============================ Hero ===================================== */

.hero {
  position: relative; overflow: hidden;
  border-radius: var(--r-xl); padding: var(--s6) var(--s4) var(--s5);
  background: linear-gradient(160deg,
      color-mix(in oklab, var(--leaf) 16%, var(--surface)),
      color-mix(in oklab, var(--accent) 13%, var(--surface)) 90%);
  border: 1px solid var(--hairline);
  box-shadow: var(--sh-1);
}
.hero__title { font-size: var(--t-2xl); letter-spacing: -0.02em; margin-bottom: var(--s2); }
.hero__sub { color: var(--ink-2); max-width: 34ch; margin: 0; }
.hero__art { position: absolute; right: -14%; top: -18%; width: 58%; max-width: 320px; opacity: 0.5; pointer-events: none; }
@media (min-width: 700px) { .hero { padding: var(--s7) var(--s6); } .hero__art { right: 2%; top: -8%; opacity: 0.8; } }

/* ============================ Search & filters ========================= */

.searchbar { position: relative; }
.searchbar .input { padding-left: 2.75rem; min-height: 3rem; border-radius: var(--r-pill); }
.searchbar__ico { position: absolute; left: var(--s3); top: 50%; translate: 0 -50%; width: 20px; height: 20px; color: var(--ink-3); pointer-events: none; }
.searchbar__clear { position: absolute; right: var(--s2); top: 50%; translate: 0 -50%; }

/* Horizontally scrolling filter rail — the mobile-first answer to a sidebar
   of checkboxes. Scroll snap keeps it feeling native under a thumb. */
.filterrail {
  display: flex; gap: var(--s2); overflow-x: auto; scroll-snap-type: x proximity;
  padding: var(--s1) var(--s4); margin: 0 calc(var(--s4) * -1);
  scrollbar-width: none;
}
.filterrail::-webkit-scrollbar { display: none; }
.filterrail > * { scroll-snap-align: start; flex: none; }
.fchip {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 2.25rem; padding: 0 var(--s3);
  border-radius: var(--r-pill); border: 1px solid var(--hairline-2);
  background: var(--surface); color: var(--ink-2);
  font-size: var(--t-sm); font-weight: 600; cursor: pointer;
  transition: all var(--dur-2) var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.fchip[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); border-color: transparent; box-shadow: var(--sh-1); }
.fchip__count { font-size: var(--t-xs); opacity: 0.7; font-variant-numeric: tabular-nums; }

/* ============================ Plant grid =============================== */

.plantgrid {
  display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
@media (min-width: 560px) { .plantgrid { gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); } }

.ptile {
  position: relative; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); overflow: hidden; text-align: left;
  cursor: pointer; text-decoration: none; color: inherit;
  box-shadow: var(--sh-1);
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
  -webkit-tap-highlight-color: transparent;
  content-visibility: auto;              /* skip layout for offscreen tiles */
  contain-intrinsic-size: 240px;
}
.ptile:active { transform: scale(0.98); }
@media (hover: hover) {
  .ptile:hover { transform: translateY(-3px); box-shadow: var(--sh-2); border-color: var(--accent-line); }
  .ptile:hover .ptile__art { transform: scale(1.06) rotate(-1.2deg); }
}
.ptile__frame {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 118%, color-mix(in oklab, var(--leaf) 15%, transparent), transparent 62%),
    linear-gradient(178deg, var(--surface-2), var(--surface-3));
  border-bottom: 1px solid var(--hairline);
}
.ptile__art { width: 100%; height: 100%; transition: transform var(--dur-4) var(--ease); }
.ptile__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity var(--dur-4) var(--ease); }
.ptile__photo.is-loaded { opacity: 1; }
.ptile__body { padding: var(--s3); display: grid; gap: 2px; flex: 1 1 auto; align-content: start; }
.ptile__name { font-family: var(--font-display); font-size: var(--t-md); font-weight: 600; letter-spacing: -0.01em; }
.ptile__bot  { font-size: var(--t-xs); font-style: italic; color: var(--ink-3); }
.ptile__foot { display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s3) var(--s3); }

/* Difficulty pip: three dots, filled to match the level. Reads instantly at
   thumbnail size where a coloured word would not. */
.pips { display: inline-flex; gap: 3px; align-items: center; }
.pips i { width: 6px; height: 6px; border-radius: 50%; background: var(--hairline-2); }
.pips[data-level="easy"] i:nth-child(-n+1),
.pips[data-level="moderate"] i:nth-child(-n+2),
.pips[data-level="challenging"] i:nth-child(-n+3) { background: var(--lvl); }
.pips[data-level="easy"] { --lvl: var(--diff-easy); }
.pips[data-level="moderate"] { --lvl: var(--diff-moderate); }
.pips[data-level="challenging"] { --lvl: var(--diff-challenging); }

.ptile__fav {
  position: absolute; top: var(--s2); right: var(--s2); z-index: 2;
  width: 2rem; height: 2rem; display: grid; place-items: center;
  border-radius: 50%; border: 0; cursor: pointer;
  background: color-mix(in oklab, var(--surface) 78%, transparent);
  backdrop-filter: blur(8px); color: var(--ink-3);
  transition: color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease-spring);
}
.ptile__fav[aria-pressed="true"] { color: var(--accent); }
.ptile__fav:active { transform: scale(1.25); }
.ptile__fav svg { width: 17px; height: 17px; }
.ptile__note { position: absolute; top: var(--s2); left: var(--s2); z-index: 2; color: var(--leaf); }
.ptile__note svg { width: 15px; height: 15px; }

/* ============================ Plant detail ============================= */

.pdetail__frame {
  position: relative; border-radius: var(--r-xl); overflow: hidden;
  aspect-ratio: 16 / 10; border: 1px solid var(--hairline);
  background:
    radial-gradient(120% 90% at 50% 116%, color-mix(in oklab, var(--leaf) 16%, transparent), transparent 62%),
    linear-gradient(178deg, var(--surface-2), var(--surface-3));
  box-shadow: var(--sh-2);
}
.pdetail__frame svg, .pdetail__frame img { width: 100%; height: 100%; object-fit: cover; }
.pdetail__photo { position: absolute; inset: 0; opacity: 0; transition: opacity var(--dur-4) var(--ease); }
.pdetail__photo.is-loaded { opacity: 1; }
.pdetail__credit { position: absolute; right: var(--s2); bottom: var(--s2); font-size: 10px;
  background: color-mix(in oklab, var(--surface) 76%, transparent); backdrop-filter: blur(6px);
  padding: 2px var(--s2); border-radius: var(--r-pill); color: var(--ink-3); }
.pdetail__title { font-size: var(--t-xl); letter-spacing: -0.02em; }
.pdetail__bot { font-style: italic; color: var(--ink-3); margin: 0; }

/* Fact grid: two columns on a phone, four on a tablet. The single most
   information-dense element in the app, so it stays visually quiet. */
.facts { display: grid; gap: var(--s2); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 620px) { .facts { grid-template-columns: repeat(4, 1fr); } }
.fact { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-md); padding: var(--s3); display: grid; gap: 2px; }
.fact__k { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--ink-3); display: flex; align-items: center; gap: 4px; }
.fact__k .ico { width: 13px; height: 13px; }
.fact__v { font-size: var(--t-sm); font-weight: 600; }

.deflist { display: grid; gap: var(--s3); }
.deflist__row { display: grid; grid-template-columns: 8.5rem 1fr; gap: var(--s3); align-items: start; }
.deflist__k { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--ink-3); padding-top: 2px; }
@media (max-width: 460px) { .deflist__row { grid-template-columns: 1fr; gap: 2px; } }

.bullets { margin: 0; padding-left: 1.1rem; display: grid; gap: var(--s2); }
.bullets li { padding-left: var(--s1); }
.bullets--warn li::marker { color: var(--warn); }

/* pH scale: a real gradient with a marked band beats "5.5–7.5" as text. */
.phscale { position: relative; height: 10px; border-radius: var(--r-pill); overflow: hidden;
  background: linear-gradient(90deg, #C9552F, #D9A02C, #4E9E5C, #3D8FA8, #5A5AA8); }
.phscale__band { position: absolute; top: 0; bottom: 0; border-radius: var(--r-pill);
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--ink); }
.phscale-wrap { display: grid; gap: var(--s1); }
.phscale-wrap .row { justify-content: space-between; font-size: 10px; color: var(--ink-3); }

/* Sowing calendar: 12 cells, lit where the plant wants to go in the ground. */
.calendar { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px; }
.calendar__m { text-align: center; padding: var(--s2) 0; border-radius: 4px; font-size: 9px; font-weight: 700;
  background: var(--surface-3); color: var(--ink-3); text-transform: uppercase; }
.calendar__m.is-on { background: var(--leaf); color: var(--accent-ink); }
.calendar__m.is-bloom { background: var(--accent); color: var(--accent-ink); }
.calendar__m.is-both { background: linear-gradient(135deg, var(--leaf) 50%, var(--accent) 50%); color: var(--accent-ink); }

/* ============================ Notes ==================================== */

.notepad { position: relative; }
.notepad .textarea {
  background: var(--surface-2);
  /* Ruled-paper feel: one hairline every line-height, drawn with a gradient. */
  background-image: repeating-linear-gradient(var(--surface-2) 0 calc(1.55em - 1px), var(--hairline) calc(1.55em - 1px) 1.55em);
  background-attachment: local; line-height: 1.55em; padding-top: 0.35em;
}
.notepad__status { font-size: var(--t-xs); color: var(--ink-3); min-height: 1.2em; }
.notepad__status.is-saved { color: var(--ok); }

/* ============================ Bouquet ================================== */

.bqitem { display: grid; grid-template-columns: 3rem 1fr auto; gap: var(--s3); align-items: center;
  padding: var(--s2) 0; border-bottom: 1px solid var(--hairline); }
.bqitem:last-child { border-bottom: 0; }
.bqitem__art { width: 3rem; height: 3rem; border-radius: var(--r-sm); overflow: hidden; background: var(--surface-2); border: 1px solid var(--hairline); }
.stepper { display: inline-flex; align-items: center; border: 1px solid var(--hairline-2); border-radius: var(--r-pill); overflow: hidden; background: var(--surface); }
.stepper button { width: 2.1rem; height: 2.1rem; border: 0; background: none; cursor: pointer; color: var(--ink-2); font-size: 1.1rem; line-height: 1; }
.stepper button:active { background: var(--surface-3); }
.stepper output { min-width: 2rem; text-align: center; font-variant-numeric: tabular-nums; font-weight: 700; font-size: var(--t-sm); }

/* Live bouquet preview — the arrangement drawn from its own stems. */
.bqpreview { aspect-ratio: 1 / 1; border-radius: var(--r-lg); border: 1px solid var(--hairline);
  background: radial-gradient(90% 70% at 50% 108%, color-mix(in oklab, var(--leaf) 16%, transparent), transparent 62%), var(--surface-2); }

/* Floating "selection tray" — persistent bouquet-in-progress on mobile. */
.tray {
  position: fixed; left: var(--s3); right: var(--s3); z-index: 70;
  bottom: calc(var(--nav-h) + var(--safe-b) + var(--s2));
  display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s2) var(--s2) var(--s4);
  background: var(--ink); color: var(--ink-invert);
  border-radius: var(--r-pill); box-shadow: var(--sh-3);
  animation: tray-in var(--dur-3) var(--ease-spring) both;
}
@keyframes tray-in { from { transform: translateY(120%); opacity: 0; } }
.tray__count { font-weight: 700; font-variant-numeric: tabular-nums; }
/* The tray floats above the tab bar, so while it is up the page needs even
   more bottom room or it sits on top of the last form field. */
body.has-tray .main { padding-bottom: calc(var(--nav-h) + var(--safe-b) + 5.5rem); }
.tray .btn { background: var(--accent); color: var(--accent-ink); border-color: transparent; box-shadow: none; }
@media (min-width: 900px) { .tray { left: auto; right: var(--s5); bottom: var(--s5); min-width: 320px; } }

/* ============================ Sales ==================================== */

.stat { padding: var(--s4); border-radius: var(--r-lg); border: 1px solid var(--hairline); background: var(--surface); display: grid; gap: var(--s1); }
.stat__v { font-family: var(--font-display); font-size: var(--t-xl); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; line-height: 1; }
.stat__k { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--ink-3); }
.statgrid { display: grid; gap: var(--s3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 700px) { .statgrid { grid-template-columns: repeat(4, 1fr); } }

.status { display: inline-flex; align-items: center; gap: var(--s2); font-size: var(--t-xs); font-weight: 700;
  padding: 3px var(--s3); border-radius: var(--r-pill); text-transform: uppercase; letter-spacing: 0.04em; }
.status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.status--draft    { background: var(--surface-3); color: var(--ink-3); }
.status--for-sale { background: var(--warn-soft); color: var(--warn); }
.status--sold     { background: var(--ok-soft); color: var(--ok); }
.status--unsold   { background: var(--danger-soft); color: var(--danger); }

/* Sparkline bars for the sales-over-time strip. */
.spark { display: flex; align-items: flex-end; gap: 3px; height: 56px; }
.spark i { flex: 1; min-height: 2px; border-radius: 2px 2px 0 0; background: var(--accent-line); transition: height var(--dur-3) var(--ease); }
.spark i.is-peak { background: var(--accent); }

/* ============================ Admin table ============================== */

.table-wrap { overflow-x: auto; border: 1px solid var(--hairline); border-radius: var(--r-lg); background: var(--surface); }
.table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); min-width: 520px; }
.table th, .table td { text-align: left; padding: var(--s3); border-bottom: 1px solid var(--hairline); vertical-align: top; }
.table th { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--ink-3); font-weight: 700;
  position: sticky; top: 0; background: var(--surface-2); z-index: 1;
  /* The wrap headers produce ("LAST SIGN-IN" over three lines) make every row
     in the table taller. The wrapper scrolls horizontally, so let them. */
  white-space: nowrap; }
.table tr:last-child td { border-bottom: 0; }
.table code { font-family: var(--font-mono); font-size: var(--t-xs); }

.auditrow { display: grid; gap: var(--s1); padding: var(--s3); border-bottom: 1px solid var(--hairline); }
.auditrow:last-child { border-bottom: 0; }
.auditrow__top { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.auditrow__act { font-family: var(--font-mono); font-size: var(--t-xs); font-weight: 700; color: var(--accent); }
.auditrow__meta { font-size: var(--t-xs); color: var(--ink-3); font-family: var(--font-mono); overflow-wrap: anywhere; }

/* ============================ Sheet / modal ============================ */

.sheet-backdrop {
  position: fixed; inset: 0; z-index: 90;
  background: color-mix(in oklab, var(--ink) 45%, transparent);
  backdrop-filter: blur(3px);
  animation: fade-in var(--dur-2) var(--ease) both;
  display: flex; align-items: flex-end; justify-content: center;
}
@keyframes fade-in { from { opacity: 0; } }
.sheet {
  width: min(100%, 560px); max-height: 88dvh; overflow-y: auto;
  background: var(--bg); border-radius: var(--r-xl) var(--r-xl) 0 0;
  border: 1px solid var(--hairline); border-bottom: 0;
  padding: var(--s3) var(--s4) calc(var(--s5) + var(--safe-b));
  box-shadow: var(--sh-3);
  animation: sheet-up var(--dur-3) var(--ease) both;
}
@keyframes sheet-up { from { transform: translateY(100%); } }
.sheet__grip { width: 2.5rem; height: 4px; border-radius: var(--r-pill); background: var(--hairline-2); margin: 0 auto var(--s4); }
.sheet__title { font-size: var(--t-lg); margin-bottom: var(--s4); }
@media (min-width: 700px) {
  .sheet-backdrop { align-items: center; }
  .sheet { border-radius: var(--r-xl); border-bottom: 1px solid var(--hairline); animation-name: sheet-pop; padding-bottom: var(--s5); }
  @keyframes sheet-pop { from { transform: scale(0.96); opacity: 0; } }
}

/* ============================ Toast ==================================== */

.toaster { position: fixed; z-index: 120; left: 0; right: 0; display: grid; justify-items: center; gap: var(--s2); pointer-events: none;
  bottom: calc(var(--nav-h) + var(--safe-b) + var(--s3)); padding: 0 var(--s4); }
@media (min-width: 900px) { .toaster { bottom: var(--s5); } }
.toast {
  pointer-events: auto; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-radius: var(--r-pill);
  background: var(--ink); color: var(--ink-invert); box-shadow: var(--sh-3);
  font-size: var(--t-sm); font-weight: 600; max-width: 30rem;
  animation: toast-in var(--dur-3) var(--ease-spring) both;
}
@keyframes toast-in { from { transform: translateY(16px) scale(0.94); opacity: 0; } }
.toast.is-out { animation: toast-out var(--dur-2) var(--ease) both; }
@keyframes toast-out { to { transform: translateY(8px); opacity: 0; } }
.toast--ok svg { color: var(--ok); } .toast--err svg { color: var(--danger); }
.toast svg { width: 18px; height: 18px; flex: none; }

/* ============================ Utility ================================== */

/* Simple mode. Contract §6: hide, never unmount, so the toggle is instant. */
[data-mode="simple"] .adv-only { display: none !important; }
[data-mode="advanced"] .simple-only { display: none !important; }

.view { animation: view-in var(--dur-3) var(--ease) both; }
@keyframes view-in { from { opacity: 0; transform: translateY(6px); } }

.skeleton { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%; animation: shimmer 1.3s infinite linear; border-radius: var(--r-md); }
@keyframes shimmer { to { background-position: -200% 0; } }

@media print {
  .topbar, .tabbar, .tray, .toaster, .btn { display: none !important; }
  body { background: #fff; }
}
