/* Font loading is injected per-app by index.html via the FONT_BLOCK placeholder.
   --font-sans / --font-display / --font-mono below are sensible fallbacks if the
   injection didn't run for some reason. The shipped index.html overrides them
   inline AFTER this stylesheet, so the per-app font group always wins. */

:root {
  --bg: #FAFAFA;
  --surface: #FFFFFF;
  --surface-2: #F4F4F5;
  --border: #E5E5E5;
  --border-strong: #D4D4D8;
  --fg: #0A0A0A;
  --fg-muted: #6B7280;
  --fg-soft: #71717A; /* ~4.6:1 on white — lifts the .soft hint tier + inactive nav toward AA */
  --accent: #0A0A0A;
  --accent-fg: #FAFAFA;
  --accent-muted: #2A2A2A;

  --tag-green-bg: #E7F5E9;  --tag-green-fg: #2C7A33;
  --tag-peach-bg: #FBE6D7;  --tag-peach-fg: #A85A1F;
  --tag-sky-bg:   #DCEEF5;  --tag-sky-fg:   #2E6A8A;
  --tag-butter-bg:#FAF3D2;  --tag-butter-fg:#8A6F1F;
  --tag-lilac-bg: #E9E4F5;  --tag-lilac-fg: #5A4B9C;

  --radius-card: 24px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-display: var(--font-sans);
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --shadow-card: 0 1px 2px rgba(10,10,10,0.04), 0 24px 48px -12px rgba(10,10,10,0.08);
  --shadow-pop: 0 8px 28px rgba(0,0,0,0.18);

  --accent-glow: #00E5FF;

  /* Floating dock surface — inverted by default (dark dock on light apps,
     light dock on dark apps). Style engine may override. */
  --dock-bg: var(--fg);
  --dock-fg: var(--bg);
}

[data-theme="dark"] {
  --bg: #0A0A0A;
  --surface: #151515;
  --surface-2: #1F1F1F;
  --border: #2A2A2A;
  --border-strong: #3A3A3A;
  --fg: #FAFAFA;
  --fg-muted: #A0A0A6;
  --fg-soft: #8A8A92; /* lifted on dark surface for AA-level hint/inactive-nav contrast */
  --accent: #FAFAFA;
  --accent-fg: #0A0A0A;
  --accent-muted: #E5E5E5;

  --tag-green-bg:#1F3522;  --tag-green-fg:#9FD3A6;
  --tag-peach-bg:#3A2618;  --tag-peach-fg:#E8B98E;
  --tag-sky-bg:  #182B36;  --tag-sky-fg:  #A1CFE2;
  --tag-butter-bg:#332C16; --tag-butter-fg:#E8D58F;
  --tag-lilac-bg:#251F36;  --tag-lilac-fg:#BFB0E6;
}

* { box-sizing: border-box; }
/* Press feel: kill the grey/blue tap-flash overlay and the 300ms double-tap
   delay on anything interactive. The :active { transform: scale() } rules
   throughout this sheet are the real, intentional press feedback instead —
   this just removes the "web page" tells that fight them. */
* { -webkit-tap-highlight-color: transparent; }
button, .button, .cell, .nav-item, .tab, .tag, .cat-card, .day, .chip,
.wxz-pill, .wxz-theme, a, label, summary, [role="button"], [data-v] {
  touch-action: manipulation;
}
html, body { margin: 0; padding: 0; min-height: 100%; }
body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  padding: 20px;
  padding-top: max(8px, env(safe-area-inset-top));
  padding-bottom: max(20px, env(safe-area-inset-bottom));
}

main.screen {
  background: transparent;
  max-width: 480px;
  margin: 0 auto;
  overflow: visible;
}

/* Header */
.screen-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 20px;
}
.screen-header h1 {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.4px;
  margin: 0 0 4px;
  color: var(--fg);
}
.screen-header .subtitle {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--fg-muted);
  margin: 0;
  letter-spacing: -0.1px;
}

/* Greeting header — the personal alternative to a title header:
   avatar + "Good morning / Name" left, 1–2 circular icon actions right. */
.greet {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}
.greet .greet-text .hi { font-size: 12px; color: var(--fg-muted); line-height: 1.3; }
.greet .greet-text .who { font-size: 17px; font-weight: 700; letter-spacing: -0.3px; color: var(--fg); }
.greet .greet-actions { margin-left: auto; display: flex; gap: 8px; }

/* Badges — sentence-case status chips ("In Progress", "Completed") */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--fg-muted);
  white-space: nowrap;
}
.badge.dark { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.badge.green { background: var(--tag-green-bg); color: var(--tag-green-fg); border-color: transparent; }
.badge.peach { background: var(--tag-peach-bg); color: var(--tag-peach-fg); border-color: transparent; }
.badge.sky   { background: var(--tag-sky-bg);   color: var(--tag-sky-fg);   border-color: transparent; }
.badge.butter{ background: var(--tag-butter-bg);color: var(--tag-butter-fg);border-color: transparent; }
.badge.lilac { background: var(--tag-lilac-bg); color: var(--tag-lilac-fg); border-color: transparent; }

/* Cards */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px;
}
.card.dashed { border-style: dashed; color: var(--fg-muted); }
/* Tinted pastel cards — colored surfaces (subscription rows, habit tiles,
   stat duos). Text inside keeps the tag ink color for contrast. */
.card.green  { background: var(--tag-green-bg);  border-color: transparent; }
.card.peach  { background: var(--tag-peach-bg);  border-color: transparent; }
.card.sky    { background: var(--tag-sky-bg);    border-color: transparent; }
.card.butter { background: var(--tag-butter-bg); border-color: transparent; }
.card.lilac  { background: var(--tag-lilac-bg);  border-color: transparent; }
/* Accent-filled feature card (the "one dominant card" pattern) */
.card.accent { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.card.accent .card-meta, .card.accent .card-label { color: var(--accent-fg); opacity: .75; }
.card .card-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  color: var(--fg-muted);
  margin-bottom: 8px;
}
.card .card-title {
  font-weight: 600;
  font-size: 15px;
  margin: 0 0 6px;
}
.card .card-meta {
  font-family: var(--font-sans);
  font-size: 11px;
  color: var(--fg-muted);
  line-height: 1.45;
}

.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.grid > *, .grid-3 > * { min-width: 0; overflow: hidden; }

/* Calendar/heatmap-style cell grid — ideal for multi-day trackers (14, 21, 30, 100 days) */
.cells {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin: 6px 0;
}
.cells.cols-5 { grid-template-columns: repeat(5, 1fr); }
.cells.cols-6 { grid-template-columns: repeat(6, 1fr); }
.cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-muted);
  cursor: pointer;
  user-select: none;
  transition: transform .1s, background .12s;
}
.cell:active { transform: scale(.94); }
.cell.done {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.cell.today { box-shadow: inset 0 0 0 2px var(--accent); }
.cell.future { opacity: .45; cursor: default; }
.cell.empty { background: transparent; border-style: dashed; }

/* Rows (label left, value right) */
.list { display: flex; flex-direction: column; }
.list .row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
  gap: 12px;
}
.list .row:last-child { border-bottom: none; }
.list .row .label { color: var(--fg); font-size: 15px; }
.list .row .value { font-family: var(--font-sans); font-weight: 600; color: var(--fg); font-size: 15px; }
.list .row .value.num { font-family: var(--font-mono); font-weight: 500; font-size: 14px; }
.list .row .strike { text-decoration: line-through; color: var(--fg-soft); font-weight: 400; margin-left: 8px; }
/* long user-entered labels truncate instead of pushing the value off-row */
.list .row > .label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list .row > .value { flex: none; }

/* Tabs */
.tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  padding: 8px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--fg-muted);
  cursor: pointer;
  flex-shrink: 0;
  white-space: nowrap;
  transition: background .12s, color .12s, border-color .12s;
}
.tab:hover { color: var(--fg); }
.tab.active { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }

/* Buttons */
button, .button {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 14px;
  padding: 12px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--fg);
  cursor: pointer;
  transition: transform .1s, background .12s, border-color .12s;
}
button:active, .button:active { transform: scale(.97); }
button:disabled { opacity: .4; cursor: not-allowed; }
button.primary, .button.primary {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
button.ghost, .button.ghost {
  background: transparent;
  border-color: transparent;
}
button.iconbtn, .button.iconbtn {
  width: 44px; height: 44px; padding: 0;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 500;
  flex-shrink: 0;
}
button.iconbtn.primary, .button.iconbtn.primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.w-full { width: 100%; display: block; }

/* Stepper */
.stepper {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 4px 8px;
}
.stepper button.iconbtn {
  width: 28px; height: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 16px;
}
.stepper .step-value {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 18px;
  min-width: 18px;
  text-align: center;
}

/* Inputs */
.input, input[type=text], input[type=number], input[type=email], input[type=date], input[type=search], input[type=tel], input[type=url], textarea {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 16px; /* >=16px prevents iOS Safari from auto-zooming on focus */
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--fg);
  outline: none;
  transition: border-color .12s;
}
.input:focus, input:focus, textarea:focus { border-color: var(--fg); }
.input::placeholder, input::placeholder, textarea::placeholder { color: var(--fg-soft); }

/* Selects — de-natived: no OS chevron, our own inline-SVG caret, pill-adjacent */
select, select.input {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-sans);
  font-size: 16px;
  padding: 12px 42px 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--fg);
  outline: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px;
}
select:focus { border-color: var(--fg); }

/* Range sliders — de-natived: tinted track + accent thumb, light/dark safe */
input[type=range] {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent) 18%, var(--surface-2));
  outline: none;
  cursor: pointer;
}
input[type=range]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--surface);
  box-shadow: 0 1px 6px rgba(0,0,0,.25);
}
input[type=range]::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--surface);
  box-shadow: 0 1px 6px rgba(0,0,0,.25);
}
input[type=range]:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---- accessibility: visible keyboard focus (mouse/touch unaffected) ---- */
button:focus-visible, .button:focus-visible, .iconbtn:focus-visible,
.cell:focus-visible, .tag:focus-visible, .day:focus-visible,
.tab:focus-visible, .seg:focus-visible, .cat-card:focus-visible,
.nav-item:focus-visible, .section-action:focus-visible, summary:focus-visible,
a:focus-visible, [role="button"]:focus-visible, [contenteditable]:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.input:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

/* ---- inline field error: message sits directly under the field it refers to ---- */
.input.invalid, input.invalid, textarea.invalid { border-color: var(--tag-peach-fg); }
.field-error {
  display: block;
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.4;
  color: var(--tag-peach-fg);
  margin-top: 6px;
}
.field-error:empty { display: none; }

/* ---- input with a trailing affordance (password reveal, clear) ---- */
.input-wrap { position: relative; }
.input-wrap > input { padding-right: 46px; }
.input-wrap > .input-affix {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg-muted); cursor: pointer;
}

/* Stat block (big hero number) */
.stat-block {
  background: var(--accent);
  color: var(--accent-fg);
  padding: 22px;
  border-radius: var(--radius-md);
  margin: 4px 0 14px;
}
.stat-block .stat-label {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  opacity: 0.65;
  margin-bottom: 10px;
}
.stat-block .stat-value {
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -1.2px;
  font-family: var(--font-sans);
  line-height: 1;
}
.stat-block .stat-value .unit {
  font-size: 24px;
  font-weight: 600;
  opacity: 0.7;
  margin-left: 4px;
}

/* Progress bar — thick track tinted from the accent so it reads as progress,
   never as a divider. .progress.slim for secondary/in-row bars. */
.progress {
  height: 10px;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface-2));
  border-radius: var(--radius-pill);
  overflow: hidden;
  margin: 6px 0;
}
.progress.slim { height: 6px; }
.progress > .progress-fill { height: 100%; background: var(--accent); border-radius: var(--radius-pill); transition: width .4s ease-out; }

/* Progress ring — conic donut with centered content. Set the percentage from
   JS via style="--ring-value:84". Size via --ring-size, stroke via --ring-w. */
.ring {
  --ring-size: 148px;
  --ring-value: 0;
  --ring-w: 13px;
  position: relative;
  width: var(--ring-size);
  aspect-ratio: 1;
  border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--ring-value) * 1%), color-mix(in srgb, var(--accent) 13%, var(--surface-2)) 0);
  transition: background .4s ease-out;
  margin: 0 auto;
  flex-shrink: 0;
}
.ring::before {
  content: '';
  position: absolute;
  inset: var(--ring-w);
  border-radius: 50%;
  background: var(--surface);
}
.ring > .ring-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 2px;
}
.ring .ring-value { font-size: 28px; font-weight: 700; letter-spacing: -0.8px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.ring .ring-sub { font-size: 11px; color: var(--fg-muted); }
.ring.ring-sm { --ring-size: 84px; --ring-w: 9px; }
.ring.ring-sm .ring-value { font-size: 18px; }

/* Rounded bar chart — flex columns, one .active bar in accent, optional
   floating value bubble on the active bar. Set fill height from JS via
   style="height:NN%" on .bar-fill. */
.bars {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 130px;
  margin: 8px 0;
}
.bars .bar {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}
.bars .bar-bubble {
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--fg);
  color: var(--bg);
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.bars .bar-fill {
  width: 100%;
  max-width: 34px;
  min-height: 6px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 16%, var(--surface-2));
  transition: height .3s ease-out;
}
.bars .bar.active .bar-fill { background: var(--accent); }
.bars .bar-label { font-size: 10px; color: var(--fg-muted); }
.progress-meta {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-sans);
  font-size: 11px;
  color: var(--fg-muted);
  margin-bottom: 12px;
}

/* Tags */
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag {
  font-size: 13px;
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--fg);
  cursor: pointer;
  user-select: none;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tag.active { background: var(--accent); color: var(--accent-fg); }
.tag.removable::after { content: ' ×'; opacity: .5; }
/* Tinted quick-add chips ("250 ml", "500 ml") — pastel pills with an icon */
.tag.green  { background: var(--tag-green-bg);  color: var(--tag-green-fg); }
.tag.peach  { background: var(--tag-peach-bg);  color: var(--tag-peach-fg); }
.tag.sky    { background: var(--tag-sky-bg);    color: var(--tag-sky-fg); }
.tag.butter { background: var(--tag-butter-bg); color: var(--tag-butter-fg); }
.tag.lilac  { background: var(--tag-lilac-bg);  color: var(--tag-lilac-fg); }

/* Day strip */
.days { display: flex; gap: 6px; margin: 4px 0 16px; }
.day {
  flex: 1;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 10px 4px;
  text-align: center;
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--fg-muted);
  text-transform: uppercase;
  cursor: pointer;
}
.day .day-icon { font-size: 22px; display: block; margin-bottom: 4px; font-family: var(--font-sans); }
.day.empty { background: transparent; border: 1px dashed var(--border-strong); }
.day.active { background: var(--accent); color: var(--accent-fg); }
.day.green   { background: var(--tag-green-bg); color: var(--tag-green-fg); }
.day.peach   { background: var(--tag-peach-bg); color: var(--tag-peach-fg); }
.day.sky     { background: var(--tag-sky-bg);   color: var(--tag-sky-fg); }
.day.butter  { background: var(--tag-butter-bg);color: var(--tag-butter-fg); }
.day.lilac   { background: var(--tag-lilac-bg); color: var(--tag-lilac-fg); }

/* Section label — sentence-case section heading ("Today's records", "Upcoming") */
.section-label {
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 650;
  letter-spacing: -0.2px;
  color: var(--fg);
  margin: 18px 0 8px;
}

/* Time-stamped list */
.timeline { display: flex; flex-direction: column; }
.timeline .item {
  display: grid;
  grid-template-columns: 70px 1fr;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.timeline .item:last-child { border-bottom: none; }
.timeline .item .when {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.2px;
  color: var(--fg-muted);
  padding-top: 3px;
}
.timeline .item .title { font-weight: 600; font-size: 15px; }
.timeline .item .sub { font-family: var(--font-sans); font-size: 11px; color: var(--fg-muted); margin-top: 2px; }

/* Lucide icons (rendered from <i data-lucide="name">) */
[data-lucide], svg.lucide {
  width: 1em;
  height: 1em;
  stroke-width: 2;
  stroke: currentColor;
  fill: none;
  vertical-align: -0.18em;
  display: inline-block;
  flex-shrink: 0;
}
.icon-lg { font-size: 22px; }
.icon-xl { font-size: 28px; }
.icon-sm { font-size: 14px; }

/* Helpers */
.mono { font-family: var(--font-mono); }
/* live-updating sans numbers keep a fixed digit width -> no width jitter per tick */
.stat-block .stat-value, .hero .hero-stat, .list .row .value, .progress-meta, .day .day-num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}
.muted { color: var(--fg-muted); }
.soft  { color: var(--fg-soft); }
.strike { text-decoration: line-through; color: var(--fg-soft); }
.small { font-size: 12px; }
.row-spread { display: flex; justify-content: space-between; align-items: center; }
.col { display: flex; flex-direction: column; gap: 8px; }
.gap-12 { gap: 12px; }
.mt-8 { margin-top: 8px; } .mt-12 { margin-top: 12px; } .mt-16 { margin-top: 16px; } .mt-20 { margin-top: 20px; }
.mb-8 { margin-bottom: 8px; } .mb-12 { margin-bottom: 12px; } .mb-16 { margin-bottom: 16px; }
.center { text-align: center; }

/* ============================================================
   UI/UX upgrade primitives (hierarchy, imagery, nav, delight,
   onboarding). All consume existing CSS variables — no hardcoded
   hex, light/dark safe. Added 2026-06.
   ============================================================ */

/* --- A. Hierarchy & hero --------------------------------- */

/* Big primary metric. The VALUE dominates; the label is small above it. */
.hero {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 28px 24px;
  margin: 4px 0 16px;
  overflow: hidden;
}
.hero.glow::before {
  content: '';
  position: absolute;
  top: -45%; left: 50%;
  transform: translateX(-50%);
  width: 240px; height: 240px;
  background: radial-gradient(circle, var(--accent-glow), transparent 70%);
  opacity: .14;
  pointer-events: none;
}
.hero > * { position: relative; }
.hero .hero-label {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-muted);
  margin-bottom: 8px;
}
.hero .hero-stat {
  font-size: 48px;
  font-weight: 700;
  letter-spacing: -2px;
  line-height: 1;
  color: var(--fg);
  font-family: var(--font-sans);
}
/* Extra-large display numeral — when the number IS the screen (temperature,
   countdown, kcal). Use inside .hero or bare. */
.hero .hero-stat.xl, .hero-stat.xl { font-size: 64px; letter-spacing: -2.5px; }
.hero .hero-stat.mono { font-family: var(--font-mono); letter-spacing: -1px; }
.hero .hero-stat .unit { font-size: 22px; font-weight: 600; color: var(--fg-muted); margin-left: 4px; }
.hero .hero-sub { font-size: 12px; color: var(--fg-muted); margin-top: 8px; }

/* Prominent top-of-screen card — distinct from plain list cards. */
.summary-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 20px;
  box-shadow: var(--shadow-card);
  margin-bottom: 16px;
}

/* Section label with a trailing action/link on the right. */
.section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 18px 0 8px;
}
.section-head .section-label { margin: 0; }
.section-head .section-action {
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
}

/* --- B. Avatars & imagery (Tier 1 / containers) ---------- */

/* Initials or icon for a person/entity. Soft colored variants below. */
.avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--accent-muted);
  color: var(--accent-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 15px;
  line-height: 1;
  flex-shrink: 0;
  text-transform: uppercase;
  overflow: hidden;
}
.avatar i, .avatar svg { width: 1.1em; height: 1.1em; }
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-sm { width: 28px; height: 28px; font-size: 11px; }
.avatar-lg { width: 56px; height: 56px; font-size: 20px; }
.avatar.green  { background: var(--tag-green-bg);  color: var(--tag-green-fg); }
.avatar.peach  { background: var(--tag-peach-bg);  color: var(--tag-peach-fg); }
.avatar.sky    { background: var(--tag-sky-bg);    color: var(--tag-sky-fg); }
.avatar.butter { background: var(--tag-butter-bg); color: var(--tag-butter-fg); }
.avatar.lilac  { background: var(--tag-lilac-bg);  color: var(--tag-lilac-fg); }

/* Square/rounded media container — holds inline SVG (Tier 2) or an emoji (Tier 3). */
.media {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  border-radius: var(--radius-md);
  overflow: hidden;
  color: var(--accent);
}
.media-tile {
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  font-size: 24px;
  flex-shrink: 0;
}
.media-tile i, .media-tile svg { width: 24px; height: 24px; }
/* Icon-in-tinted-squircle — THE standard list-row leading visual when there's
   no photo: a pastel rounded square holding an emoji or Lucide icon. */
.media-tile.green  { background: var(--tag-green-bg);  color: var(--tag-green-fg); }
.media-tile.peach  { background: var(--tag-peach-bg);  color: var(--tag-peach-fg); }
.media-tile.sky    { background: var(--tag-sky-bg);    color: var(--tag-sky-fg); }
.media-tile.butter { background: var(--tag-butter-bg); color: var(--tag-butter-fg); }
.media-tile.lilac  { background: var(--tag-lilac-bg);  color: var(--tag-lilac-fg); }
/* Photo thumb in a list row: <img class="media-thumb" data-wxz-img="..."> */
.media-thumb {
  width: 56px; height: 56px;
  border-radius: var(--radius-md);
  object-fit: cover;
  flex-shrink: 0;
  display: block;
}

/* Photo card — image-backed card with a gradient overlay and text pinned to
   the bottom (venue cards, recipe heroes, featured content). Put an
   <img data-wxz-img="..."> as the first child. Default 4:3; .wide for 16:9. */
.photo-card {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--surface-2);
}
.photo-card.wide { aspect-ratio: 16 / 9; }
.photo-card.tall { aspect-ratio: 4 / 5; }
.photo-card > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.photo-card .photo-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 3px;
  padding: 16px;
  background: linear-gradient(180deg, rgba(0,0,0,0) 38%, rgba(0,0,0,0.62));
  color: #FFFFFF;
}
.photo-card .photo-title { font-weight: 700; font-size: 17px; letter-spacing: -0.3px; }
.photo-card .photo-sub { font-size: 12px; opacity: .85; }
.photo-card .photo-overlay .badge { background: rgba(255,255,255,.18); border-color: transparent; color: #fff; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.media-hero {
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  font-size: 56px;
  position: relative;
  background: linear-gradient(135deg, var(--surface-2), var(--surface));
}
.media-hero.glow {
  background:
    radial-gradient(circle at 50% 35%, var(--accent-glow), transparent 60%),
    linear-gradient(135deg, var(--surface-2), var(--surface));
}
.media-hero svg { width: 56%; height: 56%; }

/* --- C. Navigation -------------------------------------- */

/* Floating pill dock (2–5 destinations) — detached, rounded-full, inverted
   surface. Active tab = filled accent pill. Pair with multi-view .screen-view. */
.navbar {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 40;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 4px;
  width: max-content;
  max-width: calc(100vw - 24px);
  background: var(--dock-bg, var(--fg));
  border-radius: var(--radius-pill);
  padding: 9px 12px;
  box-shadow: var(--shadow-pop);
}
.navbar .nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 8px 22px;
  min-height: 48px;
  min-width: 68px;
  background: none;
  border: none;
  border-radius: var(--radius-pill);
  color: color-mix(in srgb, var(--dock-fg, var(--bg)) 62%, transparent);
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: color .12s, background .12s, transform .1s;
}
.navbar .nav-item:active { transform: scale(.94); }
.navbar .nav-item i, .navbar .nav-item svg { width: 20px; height: 20px; }
.navbar .nav-item.active {
  background: var(--accent);
  color: var(--accent-fg);
}
/* Center FAB notched into the dock — the app's ONE primary action.
   Place it between nav-items: <button class="nav-fab"><i data-lucide="plus"></i></button> */
.navbar .nav-fab {
  width: 50px; height: 50px;
  margin: 0 4px;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: var(--accent-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  box-shadow: 0 6px 18px -4px color-mix(in srgb, var(--accent) 65%, transparent);
  transition: transform .1s;
}
.navbar .nav-fab:active { transform: scale(.92); }
.navbar .nav-fab i, .navbar .nav-fab svg { width: 22px; height: 22px; }

/* Standalone floating action button — for single-screen apps without a dock. */
.fab {
  position: fixed;
  right: 20px;
  bottom: max(20px, env(safe-area-inset-bottom));
  z-index: 38;
  width: 56px; height: 56px;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: var(--accent-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 24px -4px color-mix(in srgb, var(--accent) 55%, transparent);
  transition: transform .1s;
}
.fab:active { transform: scale(.92); }
.fab i, .fab svg { width: 24px; height: 24px; }

/* iOS-style segmented control for switching views inside one screen. */
.segmented {
  display: flex;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 3px;
  gap: 2px;
  margin-bottom: 16px;
}
.segmented .seg {
  flex: 1;
  text-align: center;
  padding: 8px 10px;
  border-radius: calc(var(--radius-sm) - 3px);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--fg-muted);
  background: none;
  border: none;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.segmented .seg.active {
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 1px 2px rgba(0,0,0,.06);
}

/* --- D. Color-coded category cards ---------------------- */

.cat-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .1s;
}
.cat-card:active { transform: scale(.98); }
.cat-card .cat-icon {
  width: 40px; height: 40px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: color-mix(in srgb, currentColor 14%, transparent);
}
.cat-card .cat-icon i, .cat-card .cat-icon svg { width: 22px; height: 22px; }
.cat-card .cat-title { font-weight: 600; font-size: 14px; }
.cat-card .cat-meta { font-size: 11px; opacity: .75; }
.cat-card.green  { background: var(--tag-green-bg);  color: var(--tag-green-fg); }
.cat-card.peach  { background: var(--tag-peach-bg);  color: var(--tag-peach-fg); }
.cat-card.sky    { background: var(--tag-sky-bg);    color: var(--tag-sky-fg); }
.cat-card.butter { background: var(--tag-butter-bg); color: var(--tag-butter-fg); }
.cat-card.lilac  { background: var(--tag-lilac-bg);  color: var(--tag-lilac-fg); }

/* --- E. Delight / peak-end ------------------------------- */

@keyframes wxz-celebrate {
  0%   { transform: scale(.8); opacity: 0; }
  55%  { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes wxz-glow-pulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50%      { box-shadow: 0 0 18px 2px var(--accent-glow); }
}
@keyframes wxz-confetti-fall {
  0%   { transform: translateY(-12px) rotate(0); opacity: 1; }
  100% { transform: translateY(72px) rotate(220deg); opacity: 0; }
}
.celebrate { animation: wxz-celebrate .5s cubic-bezier(.34,1.56,.64,1); }
.pulse { animation: wxz-glow-pulse 1.2s ease-in-out; }
.success-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  background: var(--tag-green-bg);
  color: var(--tag-green-fg);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 14px;
}
.success-badge i, .success-badge svg { width: 18px; height: 18px; }
.confetti-dot {
  position: absolute;
  width: 8px; height: 8px;
  border-radius: 2px;
  background: var(--accent);
  animation: wxz-confetti-fall .9s ease-in forwards;
}

/* --- F. Onboarding & empty states ------------------------ */

/* Interactive first-run setup. Captures the user's REAL first input,
   then renders the populated view. Never shows a cold "0" screen. */
.onboard {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 32px 20px;
  min-height: 58vh;
  min-height: 58dvh; /* dynamic viewport: respects the mobile browser toolbar */
  justify-content: center;
}
.onboard .onboard-art {
  width: 96px; height: 96px;
  display: flex; align-items: center; justify-content: center;
  color: var(--accent);
  font-size: 52px;
}
.onboard .onboard-art svg { width: 72px; height: 72px; }
.onboard h2 { font-size: 22px; font-weight: 700; letter-spacing: -0.4px; margin: 0; color: var(--fg); }
.onboard p { font-size: 14px; color: var(--fg-muted); margin: 0; max-width: 320px; }
.onboard .onboard-form {
  width: 100%; max-width: 340px;
  display: flex; flex-direction: column; gap: 12px;
  margin-top: 8px;
}
.onboard-step { width: 100%; }

/* Legitimately-empty list (after onboarding, when user has cleared items). */
.empty-state {
  text-align: center;
  padding: 36px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.empty-state .empty-art { color: var(--fg-soft); font-size: 40px; opacity: .85; }
.empty-state .empty-art svg { width: 40px; height: 40px; }
/* Art-tile empty states: <img data-wxz-img="art:..."> renders as a soft tile */
.empty-state .empty-art img, .onboard .onboard-art img {
  width: 96px; height: 96px;
  border-radius: var(--radius-card);
  object-fit: cover;
  display: block;
}
/* an arbitrary illustrative <svg> never renders at intrinsic size first (no first-paint CLS) */
.onboard-art svg, .empty-art svg, .media svg { max-width: 100%; max-height: 100%; }
.empty-state .empty-title { font-weight: 600; font-size: 15px; color: var(--fg); }
.empty-state .empty-sub { font-size: 13px; color: var(--fg-muted); max-width: 280px; }

/* --- G. Toast (transient feedback) ----------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: max(20px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 45;
  background: var(--fg);
  color: var(--bg);
  padding: 12px 20px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 13px;
  box-shadow: var(--shadow-pop);
  max-width: 90vw;
  animation: wxz-pop .3s ease-out;
}

/* Install pill (rendered by install.js) */
.wxz-pill {
  position: fixed;
  left: 50%; bottom: max(20px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 2147483646;
  background: var(--fg);
  color: var(--bg);
  padding: 13px 22px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.1px;
  box-shadow: var(--shadow-pop);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 90vw;
  animation: wxz-pop .35s ease-out;
}
.wxz-pill:active { transform: translateX(-50%) scale(.97); }
.wxz-pill .wxz-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent-glow);
  animation: wxz-pulse 1.6s infinite;
}
.wxz-pill .wxz-x {
  margin-left: 6px; opacity: .5; font-size: 16px; line-height: 1; padding: 0 4px;
}
@keyframes wxz-pop {
  from { opacity: 0; transform: translateX(-50%) translateY(20px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes wxz-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

/* Theme toggle — inline at the top-right of the centered content area
   (rendered by theme.js into the first child of <main class="screen">). */
.wxz-theme-bar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 14px;
}
.wxz-theme {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--fg);
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform .12s, background .12s, color .12s, border-color .12s;
}
.wxz-theme i,
.wxz-theme svg {
  width: 16px;
  height: 16px;
}
.wxz-theme:hover { background: var(--surface-2); }
.wxz-theme:active { transform: scale(.94); }

/* ---- multi-view utilities (used by apps that need more than one screen in one body) ---- */

.hidden { display: none !important; }

.overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  color: var(--fg);
  display: flex;
  flex-direction: column;
  padding: 24px;
  overflow-y: auto;
  animation: wxz-overlay-in .18s ease-out;
}

@keyframes wxz-overlay-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.screen-view { display: block; }

/* ---- dimmed scrim + bottom sheet / centered dialog over LIVE content ----
   Use these (not the opaque full-screen .overlay) for a confirm / picker that
   should float above the current screen. Tapping the .scrim dismisses. */
.scrim {
  position: fixed; inset: 0; z-index: 49;
  background: rgba(0,0,0,.5);
  animation: wxz-fade-in .18s ease-out;
}
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--surface); color: var(--fg);
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  padding: 20px 20px max(20px, env(safe-area-inset-bottom));
  box-shadow: var(--shadow-pop);
  animation: wxz-sheet-up .22s cubic-bezier(.2,.8,.2,1);
}
.sheet .sheet-grip { width: 36px; height: 4px; border-radius: 999px; background: var(--border-strong); margin: 0 auto 14px; }
.dialog {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%,-50%); z-index: 50;
  width: min(360px, 90vw);
  background: var(--surface); color: var(--fg);
  border-radius: var(--radius-card); padding: 22px;
  box-shadow: var(--shadow-pop); animation: wxz-celebrate .26s ease-out;
}
@keyframes wxz-sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* ---- chrome reconciliation: bottom navbar vs install pill / toast ---- */
/* When a generated app uses the floating dock, lift the install pill
   and toast above it and give the scroll area room so nothing is hidden. */
body:has(.navbar) main.screen { padding-bottom: 112px; }
body:has(.navbar) .wxz-pill   { bottom: calc(92px + env(safe-area-inset-bottom)); }
body:has(.navbar) .toast      { bottom: calc(100px + env(safe-area-inset-bottom)); }
body:has(.fab) main.screen    { padding-bottom: 100px; }

/* Bottom-pinned primary action bar — clears the home indicator automatically.
   Use this instead of a hand-rolled position:fixed;bottom:0 CTA. */
.action-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 38;
  display: flex; gap: 10px;
  padding: 12px 20px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
}
.action-bar > .button, .action-bar > button { flex: 1; }
body:has(.action-bar) main.screen { padding-bottom: 96px; }
body:has(.action-bar) .wxz-pill { bottom: calc(78px + env(safe-area-inset-bottom)); }
body:has(.action-bar) .toast    { bottom: calc(86px + env(safe-area-inset-bottom)); }

/* ---- loading skeletons (shimmer) ---- */
/* Prefer these over a bare spinner whenever content is being fetched (cloud
   reads, async lists, first paint that waits on data): render greyed blocks
   shaped like the real content, then swap in the data. Keeps the layout
   stable and the app feeling responsive instead of frozen. */
@keyframes wxz-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 37%, var(--surface-2) 63%);
  background-size: 200% 100%;
  animation: wxz-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
  color: transparent !important;
  pointer-events: none;
  user-select: none;
}
.skeleton-text   { height: 12px; margin: 7px 0; border-radius: 6px; }
.skeleton-line   { height: 16px; border-radius: 8px; }
.skeleton-block  { height: 64px; border-radius: var(--radius-md); }
.skeleton-circle { border-radius: 50%; aspect-ratio: 1; width: 44px; }
.skeleton-w-60 { width: 60%; }
.skeleton-w-40 { width: 40%; }

/* ---- subtle entrance (use sparingly — one fade per view switch / first
   render, never on every list re-render) ---- */
@keyframes wxz-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
.fade-in { animation: wxz-fade-in .22s ease-out; }

/* ---- accessibility: honor reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .celebrate, .pulse, .confetti-dot,
  .wxz-pill, .toast, .overlay, .fade-in, .skeleton,
  .scrim, .sheet, .dialog { animation: none !important; }
  * { scroll-behavior: auto !important; }
}
