/*
  Fyro — base + components for internal apps without a build step.
  Requires fyro-tokens.css first. Every class is prefixed fy- so it can sit next to an
  app's own CSS (or Tailwind) without collisions. Every colour comes from a token.

  Each component mirrors a shadcn/ui primitive (Card, Table, Select, Tabs, ToggleGroup,
  Badge, Skeleton, Alert, AlertDialog, Button), so a page built with these classes and a
  React page built with shadcn look the same.

  Contents
    1. Base           6. Forms              11. Feedback (alert, empty, skeleton)
    2. Typography     7. Segmented, tabs    12. Dialog
    3. Brand          8. Badges, chips      13. App shell
    4. Buttons        9. Table + P&L        14. Utilities
    5. Card, KPI     10. Figures
*/

/* 1. Base ---------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
* { border-color: hsl(var(--border)); }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: hsl(var(--background));
  color: hsl(var(--foreground));
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* columns align without extra classes */
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
table { border-collapse: collapse; }
code, kbd, pre, samp { font-family: var(--font-mono); font-size: 0.92em; }

a, .fy-link {
  color: hsl(var(--primary));
  text-decoration: none;
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
  font-weight: 500;
}
a:hover, .fy-link:hover { text-decoration: underline; text-underline-offset: 2px; }

:focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; }
::selection { background: hsl(var(--primary) / 0.18); }

/* 2. Typography ---------------------------------------------------------- */
/* Scale: display 34 · kpi 28 · h1 22 · h2 16 · body 14 · num 13 mono · small 12 · label 11 caps */

.fy-display { font-size: 34px; line-height: 1.1; font-weight: 600; letter-spacing: -0.03em; }
.fy-kpi     { font-size: 28px; line-height: 1;   font-weight: 600; letter-spacing: -0.02em; }
.fy-h1      { font-size: 22px; line-height: 1.25; font-weight: 600; letter-spacing: -0.015em; }
.fy-h2      { font-size: 16px; line-height: 1.35; font-weight: 600; letter-spacing: -0.01em; }
.fy-title   { font-size: 17px; line-height: 1.3; font-weight: 600; letter-spacing: -0.01em; } /* page title in the top bar */
.fy-body    { font-size: 14px; line-height: 1.5; }
.fy-small   { font-size: 12px; line-height: 1.45; }
.fy-label   { font-size: 11px; line-height: 1.3; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: hsl(var(--muted-foreground)); }
.fy-eyebrow { font-size: 10px; line-height: 1.3; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: hsl(var(--muted-foreground)); }
.fy-mono, .fy-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.fy-num     { font-size: 13px; font-weight: 500; }
.fy-muted   { color: hsl(var(--muted-foreground)); }

/* 3. Brand --------------------------------------------------------------- */
/* <span class="fy-mark"></span> <span class="fy-wordmark">Fyro <span>Finance</span></span> */

.fy-brand { display: inline-flex; align-items: center; gap: 10px; color: hsl(var(--foreground)); text-decoration: none; }
.fy-brand:hover { text-decoration: none; }
.fy-mark {
  --mark: 26px;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--mark);
  height: var(--mark);
  border-radius: calc(var(--mark) * 0.27);
  background: hsl(var(--primary));
}
.fy-mark::before {
  content: "";
  width: calc(var(--mark) * 0.35);
  height: calc(var(--mark) * 0.35);
  border-radius: calc(var(--mark) * 0.06);
  background: hsl(var(--primary-foreground));
  transform: rotate(45deg);
}
.fy-mark--sm { --mark: 22px; }
.fy-mark--lg { --mark: 36px; }
.fy-wordmark { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; line-height: 1; white-space: nowrap; }
.fy-wordmark > span { font-weight: 400; color: hsl(var(--muted-foreground)); }
.fy-wordmark--sm { font-size: 15px; }
.fy-wordmark--lg { font-size: 26px; }

/* 4. Buttons ------------------------------------------------------------- */

.fy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--h-control);
  padding: 0 12px;
  border: 1px solid hsl(var(--input));
  border-radius: var(--radius-md);
  background: hsl(var(--card));
  color: hsl(var(--foreground));
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;           /* buttons never truncate */
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s;
}
.fy-btn:hover { background: hsl(var(--accent)); text-decoration: none; }
.fy-btn:active { transform: translateY(0.5px); }
.fy-btn:disabled, .fy-btn[aria-disabled="true"] { opacity: .5; pointer-events: none; }
.fy-btn svg { width: 15px; height: 15px; flex: none; }

.fy-btn--primary { background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }
.fy-btn--primary:hover { background: hsl(var(--primary) / 0.9); }
.fy-btn--destructive { background: hsl(var(--destructive)); border-color: hsl(var(--destructive)); color: hsl(var(--destructive-foreground)); }
.fy-btn--destructive:hover { background: hsl(var(--destructive) / 0.9); }
.fy-btn--secondary { background: hsl(var(--secondary)); border-color: transparent; color: hsl(var(--secondary-foreground)); }
.fy-btn--secondary:hover { background: hsl(var(--secondary) / 0.7); }
.fy-btn--ghost { background: transparent; border-color: transparent; color: hsl(var(--muted-foreground)); font-weight: 500; }
.fy-btn--ghost:hover { background: hsl(var(--accent)); color: hsl(var(--foreground)); }
.fy-btn--link { background: none; border-color: transparent; color: hsl(var(--primary)); padding: 0 2px; font-weight: 500; }
.fy-btn--link:hover { background: none; text-decoration: underline; }

.fy-btn--sm { height: var(--h-control-sm); padding: 0 10px; font-size: 12px; }
.fy-btn--lg { height: 40px; padding: 0 16px; font-size: 14px; }
.fy-btn--icon { width: var(--h-control); padding: 0; }
.fy-btn--block { width: 100%; }

.fy-btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* 5. Card, KPI ----------------------------------------------------------- */
/* Borders first, shadow only when floating. */

.fy-card {
  background: hsl(var(--card));
  color: hsl(var(--card-foreground));
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius-xl);
  min-width: 0;
}
.fy-card--pad { padding: var(--space-6); }
.fy-card--floating { box-shadow: var(--shadow-md); }
.fy-card--subtle { background: hsl(var(--primary-subtle)); border-color: hsl(var(--primary) / 0.18); }
.fy-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px var(--space-6);
  border-bottom: 1px solid hsl(var(--border));
}
.fy-card__header--plain { border-bottom: 0; padding-bottom: 0; }
.fy-card__title { font-size: 14px; font-weight: 600; }
.fy-card__meta { font-size: 11px; color: hsl(var(--muted-foreground)); }
.fy-card__body { padding: var(--space-6); }
.fy-card__footer { padding: 12px var(--space-6); border-top: 1px solid hsl(var(--border)); font-size: 12px; color: hsl(var(--muted-foreground)); }

.fy-kpi-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 14px 16px;
  background: hsl(var(--card));
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius-xl);
}
.fy-kpi-card--md { gap: 6px; padding: 12px 16px; }
.fy-kpi-card--highlight { border-color: hsl(var(--primary) / 0.25); box-shadow: 0 0 0 1px hsl(var(--primary) / 0.1); }
.fy-kpi-card__head { display: flex; justify-content: space-between; gap: 8px; }
.fy-kpi-card__label { font-size: 11px; font-weight: 500; color: hsl(var(--muted-foreground)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fy-kpi-card--highlight .fy-kpi-card__label { color: hsl(var(--primary)); }
.fy-kpi-card__unit { font-size: 10px; color: hsl(var(--muted-foreground)); }
.fy-kpi-card__value { font-size: 25px; font-weight: 600; line-height: 1; letter-spacing: -0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fy-kpi-card--md .fy-kpi-card__value { font-size: 22px; }
.fy-kpi-card__deltas { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.fy-delta { display: inline-flex; align-items: baseline; gap: 4px; }
.fy-delta > b { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
.fy-delta > span { font-size: 10px; color: hsl(var(--muted-foreground)); }

.fy-kpi-row { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }

/* Sparkline: <svg class="fy-spark fy-spark--positive" viewBox="0 0 11 24" preserveAspectRatio="none"><polyline …/></svg> */
.fy-spark { display: block; width: 100%; height: 24px; overflow: visible; }
.fy-spark polyline, .fy-spark path { fill: none; stroke: hsl(var(--muted-foreground)); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.fy-spark--positive polyline, .fy-spark--positive path { stroke: hsl(var(--positive)); }
.fy-spark--negative polyline, .fy-spark--negative path { stroke: hsl(var(--negative)); }
.fy-spark--primary polyline, .fy-spark--primary path { stroke: hsl(var(--primary)); }

/* 6. Forms --------------------------------------------------------------- */

.fy-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.fy-field__label { font-size: 12px; font-weight: 500; color: hsl(var(--foreground)); }
.fy-field__help { font-size: 12px; color: hsl(var(--muted-foreground)); }
.fy-field__error { font-size: 12px; color: hsl(var(--negative)); }

.fy-input, .fy-select, .fy-textarea {
  width: 100%;
  height: var(--h-control);
  padding: 0 10px;
  border: 1px solid hsl(var(--input));
  border-radius: var(--radius-md);
  background: hsl(var(--card));
  color: hsl(var(--foreground));
  font-size: 13px;
  transition: border-color .15s, box-shadow .15s;
}
.fy-textarea { height: auto; min-height: 80px; padding: 8px 10px; line-height: 1.5; resize: vertical; }
.fy-input::placeholder, .fy-textarea::placeholder { color: hsl(var(--muted-foreground)); }
.fy-input:focus, .fy-select:focus, .fy-textarea:focus { outline: none; border-color: hsl(var(--ring)); box-shadow: 0 0 0 3px hsl(var(--ring) / 0.18); }
.fy-input[aria-invalid="true"], .fy-select[aria-invalid="true"], .fy-textarea[aria-invalid="true"] { border-color: hsl(var(--negative)); }
.fy-input:disabled, .fy-select:disabled, .fy-textarea:disabled { opacity: .55; cursor: not-allowed; }
.fy-input--num { font-family: var(--font-mono); text-align: right; }

.fy-select {
  appearance: none;
  -webkit-appearance: none;
  width: auto;
  min-width: 0;
  padding-right: 28px;
  font-weight: 500;
  cursor: pointer;
  /* chevron drawn with two gradients so it follows the text colour token */
  background-image:
    linear-gradient(45deg, transparent 50%, hsl(var(--muted-foreground)) 50%),
    linear-gradient(135deg, hsl(var(--muted-foreground)) 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 10px) 50%;
  background-size: 4px 4px;
  background-repeat: no-repeat;
}
.fy-select--block { width: 100%; }

.fy-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.fy-check input:not(.fy-switch) { width: 16px; height: 16px; margin: 0; accent-color: hsl(var(--primary)); cursor: pointer; }

.fy-switch { appearance: none; -webkit-appearance: none; position: relative; width: 32px; height: 18px; margin: 0; border-radius: 999px; background: hsl(var(--input)); cursor: pointer; transition: background-color .15s; flex: none; }
.fy-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: hsl(var(--card)); box-shadow: var(--shadow-sm); transition: transform .15s; }
.fy-switch:checked { background: hsl(var(--primary)); }
.fy-switch:checked::after { transform: translateX(14px); }

.fy-form-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* 7. Segmented control, tabs --------------------------------------------- */
/* Month/Quarter/Year, EUR/USD, EN/IT, light/dark. role="radiogroup" + buttons role="radio". */

.fy-segmented { display: inline-flex; padding: 2px; border: 1px solid hsl(var(--border)); border-radius: var(--radius-lg); background: hsl(var(--muted)); }
.fy-segmented > button, .fy-segmented > a {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  flex: 1;
  padding: 4px 10px;
  border: 0;
  border-radius: calc(var(--radius-lg) - 3px);
  background: transparent;
  color: hsl(var(--muted-foreground));
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color .15s, background-color .15s;
}
.fy-segmented > :hover { color: hsl(var(--foreground)); text-decoration: none; }
.fy-segmented > [aria-checked="true"], .fy-segmented > [aria-selected="true"], .fy-segmented > .is-active {
  background: hsl(var(--card)); color: hsl(var(--foreground)); font-weight: 600; box-shadow: var(--shadow-sm);
}
.fy-segmented--sm > button, .fy-segmented--sm > a { padding: 4px 8px; font-size: 11px; }

.fy-tabs { display: flex; gap: 20px; border-bottom: 1px solid hsl(var(--border)); overflow-x: auto; scrollbar-width: none; }
.fy-tabs > a, .fy-tabs > button {
  padding: 10px 0;
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: hsl(var(--muted-foreground));
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.fy-tabs > :hover { color: hsl(var(--foreground)); text-decoration: none; }
.fy-tabs > [aria-selected="true"], .fy-tabs > .is-active { color: hsl(var(--foreground)); border-bottom-color: hsl(var(--primary)); font-weight: 600; }

/* 8. Badges, chips ------------------------------------------------------- */

.fy-badge {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: hsl(var(--secondary));
  color: hsl(var(--muted-foreground));
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.fy-badge--income   { background: hsl(var(--pl-income));   color: hsl(var(--pl-income-ink)); }
.fy-badge--expense  { background: hsl(var(--pl-cost-2));   color: hsl(var(--pl-cost-2-ink)); }
.fy-badge--positive { background: hsl(var(--positive) / 0.12); color: hsl(var(--positive)); }
.fy-badge--negative { background: hsl(var(--negative) / 0.12); color: hsl(var(--negative)); }
.fy-badge--warning  { background: hsl(var(--warning) / 0.14);  color: hsl(var(--warning)); }
.fy-badge--primary  { background: hsl(var(--primary-subtle));  color: hsl(var(--primary)); }
.fy-badge--code     { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.02em; }
.fy-badge--outline  { background: transparent; border-color: hsl(var(--border)); color: hsl(var(--muted-foreground)); font-weight: 500; }
.fy-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

/* Filter chip: <span class="fy-chip">Bank: Wise EUR <button aria-label="Remove">×</button></span> */
.fy-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px;
  padding: 0 4px 0 9px;
  border: 1px solid hsl(var(--primary) / 0.2);
  border-radius: var(--radius-sm);
  background: hsl(var(--primary-subtle));
  color: hsl(var(--pl-key-ink));
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.fy-chip > button {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: inherit;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  opacity: .7;
}
.fy-chip > button:hover { opacity: 1; background: hsl(var(--primary) / 0.12); }

.fy-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Legend swatch for categorical slots: <span class="fy-swatch fy-cc-3"></span> */
.fy-swatch { display: inline-block; width: 8px; height: 8px; border-radius: 2px; background: hsl(var(--cc-rest)); flex: none; }

/* 9. Table + P&L --------------------------------------------------------- */
/* Row 38px. Sticky header and first column. Numeric cells mono, right-aligned, no vertical rules. */

.fy-table-wrap { position: relative; overflow: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
.fy-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
.fy-table th, .fy-table td {
  height: var(--h-row);
  padding: 0 12px;
  border-bottom: 1px solid hsl(var(--border));
  text-align: left;
  white-space: nowrap;
  vertical-align: middle;
}
.fy-table thead th {
  position: sticky; top: 0; z-index: 2;
  height: 34px;
  background: hsl(var(--muted));
  color: hsl(var(--muted-foreground));
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: normal;           /* headers wrap to two lines rather than truncate */
}
.fy-table th:first-child, .fy-table td:first-child { position: sticky; left: 0; z-index: 1; background: hsl(var(--card)); padding-left: 16px; }
.fy-table thead th:first-child { z-index: 3; background: hsl(var(--muted)); }
.fy-table th:last-child, .fy-table td:last-child { padding-right: 16px; }
.fy-table tbody tr:last-child td { border-bottom: 0; }
.fy-table tbody tr:hover td { background-color: hsl(var(--accent) / 0.6); }
.fy-table .is-num, .fy-table td.fy-num { text-align: right; font-family: var(--font-mono); font-size: 13px; font-weight: 500; }
.fy-table th.is-num { text-align: right; }
.fy-table--compact th, .fy-table--compact td { height: 32px; }
.fy-table--clickable tbody tr { cursor: pointer; }

/* P&L rows: tint + 3px side bar + ink. Put the modifier on the <tr>. */
.fy-pl > td { font-weight: 600; }
.fy-pl > td:first-child { box-shadow: inset 3px 0 0 var(--pl-bar, transparent); }
.fy-pl > td { background: var(--pl-row) !important; color: var(--pl-ink, inherit); }
.fy-pl--income   { --pl-row: hsl(var(--pl-income));   --pl-bar: hsl(var(--pl-income-bar));   --pl-ink: hsl(var(--pl-income-ink)); }
.fy-pl--cost-1   { --pl-row: hsl(var(--pl-cost-1));   --pl-bar: hsl(var(--pl-cost-1-bar));   --pl-ink: hsl(var(--pl-cost-1-ink)); }
.fy-pl--cost-2   { --pl-row: hsl(var(--pl-cost-2));   --pl-bar: hsl(var(--pl-cost-2-bar));   --pl-ink: hsl(var(--pl-cost-2-ink)); }
.fy-pl--cost-3   { --pl-row: hsl(var(--pl-cost-3));   --pl-bar: hsl(var(--pl-cost-3-bar));   --pl-ink: hsl(var(--pl-cost-3-ink)); }
.fy-pl--income-2 { --pl-row: hsl(var(--pl-income-2)); --pl-bar: hsl(var(--pl-income-2-bar)); --pl-ink: hsl(var(--pl-income-2-ink)); }
.fy-pl--cost-4   { --pl-row: hsl(var(--pl-cost-4));   --pl-bar: hsl(var(--pl-cost-4-bar));   --pl-ink: hsl(var(--pl-cost-4-ink)); }
.fy-pl--subtotal { --pl-row: hsl(var(--pl-subtotal)); --pl-bar: hsl(var(--pl-subtotal-bar)); --pl-ink: hsl(var(--foreground)); }
.fy-pl--key      { --pl-row: hsl(var(--pl-key));      --pl-bar: hsl(var(--primary));         --pl-ink: hsl(var(--pl-key-ink)); }
.fy-pl--total    { --pl-row: hsl(var(--pl-total));    --pl-bar: hsl(var(--pl-total));        --pl-ink: hsl(var(--pl-total-ink)); }
.fy-pl--total > td .fy-neg, .fy-pl--total > td .fy-pos { color: inherit; }  /* never red-on-colour fill */
/* A line inside a section */
.fy-table td.fy-indent { padding-left: 32px; }

/* 10. Figures ------------------------------------------------------------ */
/* Format with fyro-format.js; these classes only colour the result. */

.fy-pos  { color: hsl(var(--positive)); }
.fy-neg  { color: hsl(var(--negative)); }
.fy-warn { color: hsl(var(--warning)); }
.fy-zero, .fy-missing { color: hsl(var(--muted-foreground)); }
.fy-amount { font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Multi-currency, one line per currency, largest first */
.fy-amount-stack { display: flex; flex-direction: column; gap: 2px; font-family: var(--font-mono); font-size: 13px; font-weight: 600; }
.fy-amount-stack > :nth-child(n+3) { font-weight: 400; color: hsl(var(--muted-foreground)); font-size: 12px; }

/* Key/value list (dialog summaries, details panes) */
.fy-kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: 13px; }
.fy-kv > dt { color: hsl(var(--muted-foreground)); }
.fy-kv > dd { text-align: right; font-family: var(--font-mono); }
.fy-kv--box { padding: 12px 14px; border: 1px solid hsl(var(--border)); border-radius: var(--radius-md); background: hsl(var(--muted)); }

/* 11. Feedback: alert, empty state, skeleton ------------------------------ */

.fy-alert {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 16px;
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius-lg);
  background: hsl(var(--card));
  font-size: 13px;
}
.fy-alert__title { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 14px; }
.fy-alert__title::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: hsl(var(--muted-foreground)); flex: none; }
.fy-alert__body { color: hsl(var(--muted-foreground)); }
.fy-alert--error   { border-color: hsl(var(--negative) / 0.3); }
.fy-alert--error   .fy-alert__title::before { background: hsl(var(--negative)); }
.fy-alert--warning { border-color: hsl(var(--warning) / 0.35); background: hsl(var(--warning) / 0.06); }
.fy-alert--warning .fy-alert__title::before { background: hsl(var(--warning)); }
.fy-alert--success { border-color: hsl(var(--positive) / 0.3); }
.fy-alert--success .fy-alert__title::before { background: hsl(var(--positive)); }
.fy-alert--info    { border-color: hsl(var(--primary) / 0.25); background: hsl(var(--primary-subtle)); }
.fy-alert--info    .fy-alert__title::before { background: hsl(var(--primary)); }
.fy-alert__eyebrow { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; color: hsl(var(--negative)); }
.fy-alert__eyebrow::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

.fy-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 32px 24px;
  text-align: center;
}
.fy-empty__icon { display: grid; place-items: center; width: 40px; height: 40px; margin-bottom: 8px; border: 1px solid hsl(var(--border)); border-radius: var(--radius-lg); background: hsl(var(--muted)); color: hsl(var(--muted-foreground)); }
.fy-empty__icon svg { width: 18px; height: 18px; }
.fy-empty__title { font-size: 15px; font-weight: 600; }
.fy-empty__body { max-width: 320px; font-size: 13px; color: hsl(var(--muted-foreground)); }
.fy-empty .fy-btn-row { justify-content: center; margin-top: 8px; }

/* Same box, same height as the loaded content. No spinners, no layout shift. */
.fy-skeleton { display: block; height: 12px; border-radius: var(--radius-md); background: hsl(var(--muted)); animation: fy-pulse 1.6s ease-in-out infinite; }
.fy-skeleton--title { height: 24px; width: 55%; }
.fy-skeleton--line  { height: 10px; width: 40%; }
.fy-skeleton--block { height: 28px; width: 100%; }
@keyframes fy-pulse { 50% { opacity: .55; } }

/* 12. Dialog (native <dialog>) ------------------------------------------- */

.fy-dialog {
  width: min(440px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius-xl);
  background: hsl(var(--popover));
  color: hsl(var(--popover-foreground));
  box-shadow: var(--shadow-xl);
}
.fy-dialog::backdrop { background: hsl(224 24% 12% / 0.4); }
.fy-dialog__body { display: flex; flex-direction: column; gap: 14px; padding: 24px; }
.fy-dialog__title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.fy-dialog__text { font-size: 13px; color: hsl(var(--muted-foreground)); }
.fy-dialog__actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }

/* Popover / menu surface */
.fy-popover { padding: 4px; border: 1px solid hsl(var(--border)); border-radius: var(--radius-lg); background: hsl(var(--popover)); box-shadow: var(--shadow-lg); }
.fy-menu-item { display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 10px; border: 0; border-radius: 6px; background: none; text-align: left; font-size: 13px; color: hsl(var(--popover-foreground)); cursor: pointer; }
.fy-menu-item:hover, .fy-menu-item:focus-visible { background: hsl(var(--accent)); outline: none; }

/* 13. App shell ---------------------------------------------------------- */
/*
  <div class="fy-app">
    <aside class="fy-sidebar">…</aside>
    <div class="fy-main">
      <header class="fy-topbar">…</header>
      <div class="fy-filterbar">…</div>
      <main class="fy-page">…</main>
    </div>
  </div>
*/

.fy-app { display: grid; grid-template-columns: var(--w-sidebar) minmax(0, 1fr); min-height: 100vh; min-height: 100dvh; }
.fy-app--collapsed { grid-template-columns: var(--w-sidebar-collapsed) minmax(0, 1fr); }
.fy-main { display: flex; flex-direction: column; min-width: 0; }

.fy-sidebar {
  position: sticky; top: 0;
  display: flex; flex-direction: column; gap: 4px;
  height: 100vh; height: 100dvh;
  padding: 14px 10px;
  border-right: 1px solid hsl(var(--sidebar-border));
  background: hsl(var(--sidebar-background));
  color: hsl(var(--sidebar-foreground));
  overflow-y: auto;
}
.fy-sidebar__brand { display: flex; align-items: center; height: 36px; padding: 0 8px; margin-bottom: 14px; }
.fy-sidebar__section { padding: 14px 10px 6px; font-size: 10px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: hsl(var(--muted-foreground)); }
.fy-sidebar__foot { margin-top: auto; padding-top: 12px; border-top: 1px solid hsl(var(--sidebar-border)); }
.fy-nav-item {
  display: flex; align-items: center; gap: 10px;
  height: 34px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: hsl(var(--sidebar-foreground));
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;           /* nav items never truncate */
  text-decoration: none;
}
.fy-nav-item svg { width: 16px; height: 16px; flex: none; opacity: .8; }
.fy-nav-item:hover { background: hsl(var(--sidebar-accent)); color: hsl(var(--sidebar-accent-foreground)); text-decoration: none; }
.fy-nav-item[aria-current="page"], .fy-nav-item.is-active {
  background: hsl(var(--sidebar-accent));
  border-color: hsl(var(--sidebar-border));
  color: hsl(var(--sidebar-accent-foreground));
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.fy-nav-item[aria-current="page"] svg, .fy-nav-item.is-active svg { color: hsl(var(--sidebar-primary)); opacity: 1; }
.fy-app--collapsed .fy-nav-item { justify-content: center; padding: 0; }
.fy-app--collapsed .fy-nav-item > span,
.fy-app--collapsed .fy-sidebar__section,
.fy-app--collapsed .fy-wordmark { display: none; }

.fy-topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 12px;
  height: var(--h-topbar);
  padding: 0 var(--space-8);
  border-bottom: 1px solid hsl(var(--border));
  background: hsl(var(--background) / 0.92);
  backdrop-filter: saturate(1.4) blur(8px);
}
.fy-topbar__title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; white-space: nowrap; }
.fy-topbar__actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.fy-filterbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  min-height: var(--h-filterbar);
  padding: 10px var(--space-8);
  border-bottom: 1px solid hsl(var(--border));
  background: hsl(var(--card));
}
.fy-filterbar__meta { font-family: var(--font-mono); font-size: 11px; color: hsl(var(--muted-foreground)); }

.fy-page { display: flex; flex-direction: column; gap: var(--space-6); width: 100%; max-width: 1440px; padding: var(--space-6) var(--space-8) var(--space-12); }
.fy-page--narrow { max-width: 880px; }
.fy-page__head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; }
.fy-page__sub { margin-top: 4px; font-size: 13px; color: hsl(var(--muted-foreground)); }

.fy-grid { display: grid; gap: var(--space-6); }
.fy-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fy-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fy-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.fy-stack { display: flex; flex-direction: column; gap: var(--space-4); }
.fy-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }

/* Mobile: off-canvas sidebar, 16px gutter, 44px touch targets */
.fy-menu-toggle { display: none; }
@media (max-width: 900px) {
  .fy-grid--3, .fy-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
  .fy-app, .fy-app--collapsed { grid-template-columns: minmax(0, 1fr); }
  .fy-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 50; width: min(280px, 85vw); transform: translateX(-100%); transition: transform .2s, box-shadow .2s; }
  .fy-app.is-nav-open .fy-sidebar { transform: none; box-shadow: var(--shadow-xl); }
  .fy-menu-toggle { display: inline-flex; }
  .fy-topbar, .fy-filterbar { padding-left: var(--space-4); padding-right: var(--space-4); }
  .fy-page { padding: var(--space-4) var(--space-4) var(--space-8); gap: var(--space-4); }
  .fy-grid--2, .fy-grid--3, .fy-grid--4 { grid-template-columns: minmax(0, 1fr); }
  .fy-card--pad, .fy-card__body { padding: var(--space-4); }
  .fy-card__header { padding: 14px var(--space-4); }
  .fy-btn, .fy-input, .fy-select { min-height: var(--h-touch); }
  .fy-nav-item { height: var(--h-touch); }
  .fy-segmented > button, .fy-segmented > a { min-height: 40px; }
}

/* 14. Utilities ---------------------------------------------------------- */

.fy-bg-cc-1 { background: hsl(var(--cc-1)); }  .fy-bg-cc-2 { background: hsl(var(--cc-2)); }
.fy-bg-cc-3 { background: hsl(var(--cc-3)); }  .fy-bg-cc-4 { background: hsl(var(--cc-4)); }
.fy-bg-cc-5 { background: hsl(var(--cc-5)); }  .fy-bg-cc-6 { background: hsl(var(--cc-6)); }
.fy-bg-cc-7 { background: hsl(var(--cc-7)); }  .fy-bg-cc-8 { background: hsl(var(--cc-8)); }
.fy-bg-cc-9 { background: hsl(var(--cc-9)); }  .fy-bg-cc-10 { background: hsl(var(--cc-10)); }
.fy-bg-cc-rest { background: hsl(var(--cc-rest)); }

.fy-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.fy-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.fy-right { text-align: right; }
.fy-nowrap { white-space: nowrap; }
.fy-divider { height: 1px; border: 0; margin: 0; background: hsl(var(--border)); }

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