/* =====================================================================
   FairExposure Design System · v2.0 (Claude Design, 26 Oct 2026)
   "Gute Arbeit. Faire Preise."

   Source of truth: the "FairExposure" design system artifact (tokens.json,
   components/bundle.css, the README's nine rules, 07-interface.md).
   Token names in section 1 are the design system's own (var(--kobalt),
   var(--surface) …); use them, never raw values.

   Tokens (0.8.9: fully tokenised; scripts/check-tokens.py fails the build on a raw value)
     Tier 1 · Primitives — the palette and every scale: colour hues, space, size, type size,
              leading, tracking, weight, radius, stroke, opacity, z-index, duration, easing.
     Tier 2 · Semantic   — roles built on tier 1: surface / text / line / status colours, focus,
              the type roles (--fe-text-price, --fe-text-pull …), layers (--z-dialog …).
     Tier 3 · Component  — named dimensions of one component (--switch-w, --xline-price-w …):
              design-system components in 1d below, app components at the top of app.css,
              the quote document in 1c (--doc-*).
     Rule: a raw value lives only in a token definition. Declarations use var(); calc() may
     multiply a token by a plain number (calc(var(--space-2) * -1)). Exempt: 0, auto, %, fr,
     viewport units, keywords, url() data, and media/container query widths, which cannot
     read custom properties: they use the breakpoints listed in 1e.
     Export: scripts/export-tokens.py writes Brand/tokens/fairexposure.tokens.json (W3C design
     tokens format) for design tools; CI checks it is current.

   1. Tokens · 1b. App tokens · 1c. Quote document · 1d. Component tokens · 1e. Breakpoints
   2. Base and type styles
   3. Brand (wordmark)
   4. Components (button, segmented control, chips, fields, stepper,
      switch, toggle row, card, alert, badge, toast, dialog)
   5. Motion primitives
   6. Reduced motion

   Interface rules: ink on cream. Square (radius-0) except cards and
   dialogs (radius-card). Flat: no shadows, no gradients. State is ink
   (0.8.9, was the RGB light beam): the current step, what you chose, a
   toast's time. Colour is for the start screen and the logo, never beside
   a price. Colour layers carry a fine film grain (0.8.7).
   Graphic elements (3b) each have one job; see app.css «Licht».
   Kobalt marks focus (2px ring, 2px offset), links and info; the other
   hues are never text. One ink per line of type. No paper grain in the app.
   Numbers (0.8.8): an amount that stands as data — a value, a total, a table cell, the amount in a label line
   («Auftragspauschale CHF 185.00») — is IBM Plex Mono, tabular. Inside a running sentence an amount stays in the
   sentence's font: one typeface per sentence reads better than a font switch mid-line.
   Quote documents keep their neutral fonts (Source Serif 4 + Geist),
   because the quote carries the photographer's brand, not ours.
   ===================================================================== */

/* ---------- 1. Tokens ---------- */
:root{
  color-scheme: light;

  /* Brand colours: a ground, an ink and five hues that behave like light */
  --kobalt:    #2C5BFF;   /* lead hue · links, info, the focus ring */
  --kobalt-soft: #F0F3FF;   /* quiet blue entry-card surface */
  --limette:   #D8F05A;
  --koralle:   #FF7A59;
  --magenta:   #E85AA8;
  --petrol:    #20B8B0;
  --warmweiss: #FBFAF8;   /* the ground: a clean, barely warm white (also <meta name="theme-color">) */
  --tinte:     #17181A;   /* all type: a crisp warm near-black (0.9.2) */
  /* Light (0.9.2): translucent discs from the brand palette only; magenta and limette overlap to a warm orange (multiply) */
  --disc-m:      var(--magenta);   /* your work */
  --disc-y:      var(--limette);   /* the usage */
  --disc-o:      var(--koralle);   /* the overlap, the fair price (flat use, where no blend is possible) */
  --accent:      var(--disc-o);
  --accent-ink:  var(--kobalt);   /* links and focus: kobalt, as the design system says */
  --accent-soft: #FFF0EB;   /* the client-text card: a breath of koralle */
  --accent-line: #FFD6C9;

  /* Semantic colours (contrast notes: see the design system's Colour page) */
  --surface:            var(--warmweiss);
  --surface-raised:     #FFFFFF;   /* cards, panels, fields: white on paper */
  --surface-hover:      #F4F2EF;   /* hover on ghost buttons, menu and nav items, rows */
  --surface-active:     #ECE9E5;   /* current nav item, pressed */
  --text:               var(--tinte);
  --text-muted:         #55575B;
  --text-subtle:        #6B6D70;   /* tertiary detail, only on surface and surface-raised */
  --text-inverse:       var(--warmweiss);
  --text-inverse-muted: #A9A49B;
  --line:               #ECEAE6;   /* hairlines between rows */
  --line-strong:        #8D8A84;   /* control borders (3.4:1), section rules */
  --line-soft:          #ECEAE6;   /* card edges */
  --koralle-tint:       #FCDACC;   /* the total row of a quote */
  --focus:              var(--accent-ink);
  --link:               var(--accent-ink);
  --scrim:              #17181A52; /* ink at 32 % behind a dialog */
  --info:    var(--accent-ink); --info-tint: #F4F2EF;   /* notes on a quiet warm neutral */
  --success: #08716A;        --success-tint: #C6E4DC;
  --warning: #5A6600;        --warning-tint: #EAF1B2;
  --danger:  #B23A1F;        --danger-tint:  var(--koralle-tint);

  /* Type: four families, one job each */
  --font-serif:   var(--font-sans);                                              /* 0.9.2: titles in the same grotesk, larger and tighter */
  --font-sans:    "Geist", "Helvetica Neue", Arial, sans-serif;                  /* every word, title and number */
  --font-figures: var(--font-sans);                                              /* numbers as data: tabular figures, no monospace */

  /* Spacing (8px steps; two optical steps below them for hairline nudges) */
  --space-px: 1px; --space-half: 2px;
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px; --space-5: 24px;
  --space-6: 32px; --space-7: 48px; --space-8: 64px; --space-9: 96px;

  /* Radius: square by default; one small radius for cards and dialogs */
  --radius-0: 0; --radius-sm: 6px; --radius-control: 10px; --radius-card: 14px; --radius-dialog: 18px; --radius-pill: 999px; --radius-round: 50%;   /* 0.9.1: soft, never sharp */

  /* Size */
  --size-px: 1px;
  --control-xs: 36px; --control-sm: 32px; --control-md: 40px; --control-lg: 48px;
  --control-touch: 44px;   /* the minimum touch target (WCAG 2.5.5) */
  --icon-sm: 16px; --icon-md: 20px; --icon-lg: 24px;
  --header-height: 64px; --sidebar-width: 248px; --content-max: 1200px; --measure: 68ch;

  /* Stroke and opacity */
  --stroke-hairline: 1px; --stroke-mark: 2px; --stroke-bar: 3px;   /* bar: progress steps, the chosen tab, the toast's time */
  --shadow-knob: 0 1px 2px #17181A1F, 0 0 0 1px #17181A0D;   /* the only shadow: a knob that sits on its track */
  --opacity-disc: .72;   /* a disc of light: overlaps mix, the ground shows through */
  --opacity-overlay: .85; --opacity-veil: .4; --opacity-pulse: .35; --opacity-hover: .12; --opacity-disabled: .45;

  /* Type: weight, leading and tracking (sizes in 1b) */
  --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700; --weight-heavy: 800;
  --leading-none: 1; --leading-display: 1.05; --leading-tight: 1.1; --leading-snug: 1.2; --leading-body: 1.5;
  --leading-2xs: 14px; --leading-xs: 16px; --leading-sm: 18px; --leading-ui: 20px; --leading-md: 22px; --leading-pull: 26px; --leading-lg: 28px;
  --tracking-tighter: -.03em; --tracking-tight: -.02em; --tracking-snug: -.01em; --tracking-ui: .01em; --tracking-wide: .04em;
  --tracking-caps-sm: .08em; --tracking-caps: .14em; --tracking-eyebrow: .2em;   /* capitals: small labels, tracked caps, the eyebrow */
  --word-spacing-caps: .12em;

  /* Focus and links */
  --focus-offset: 2px; --underline-offset: 3px; --baseline-nudge: 1px;

  /* Layers: one scale, named by what sits there */
  --z-raised: 2; --z-panel-head: 5; --z-sticky: 10; --z-sticky-foot: 12; --z-header: 20; --z-menu: 30; --z-dock: 40;
  --z-sheet-scrim: 56; --z-sheet: 57; --z-scrim: 60; --z-dialog: 61; --z-panel-scrim: 65; --z-panel-sheet: 70; --z-toast: 90; --z-toast-under-modal: 55;

  /* The beam (0.8.9): ink. It was three overlapping gels (0.8.7); in the flow they read as decoration, so state
     marks are one solid ink. Kept as a token so every use stays one line. */
  --beam: linear-gradient(var(--tinte), var(--tinte));

  /* Film grain (0.8.7): a fine noise used as a mask, so every colour layer reads like light on film.
     Applied to graphic elements only; type, controls and the logo stay clean. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.05' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.75 1.3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  --grain-size: 160px;

  /* Motion: 120ms for colour, 160–240ms for movement */
  --ease: cubic-bezier(.2,.7,.2,1);       /* ease-out: things arriving, state changes */
  --ease-in: cubic-bezier(.4,0,1,1);      /* things leaving */
  --ease-calm: cubic-bezier(.3,0,.2,1);   /* soft start and landing: a large card answering the pointer */

  /* Motion choreography (0.9.0): transform and opacity only, 120–240 ms, nothing loops */
  --motion-stagger: 28ms;                 /* between siblings entering one after another */
  --motion-rise: var(--space-2);          /* how far an entering element travels */
  --motion-shift: var(--space-3);         /* a screen entering from the side it comes from */
  --motion-press: .98;                    /* scale of a pressed control */
  --motion-pop: .6;                       /* scale a tick starts from */
  --motion-grow: .92;                     /* scale a graphic grows from */

  /* ---- 1b. App tokens: layout, type scale and timing on top of the design system ---- */
  --fe-line:   var(--line);          /* overridden inside the quote letter by --fe-doc-line */
  --fe-line-2: var(--line-strong);   /* overridden inside the quote letter by --fe-doc-line-2 */

  /* Type scale (0.8.8: every UI size is one of these; the quote document keeps its own metrics in 1c / app.css) */
  --fe-text-2xs: 11px;                              /* eyebrow: tracked capitals only */
  --fe-text-xs: 12px;                               /* section-label, meta */
  --fe-text-sm: 13px;                               /* small: hints, secondary lines */
  --fe-text-ui: 14px;                               /* label: buttons, chips, fields' labels, nav */
  --fe-text-md: 15px;                               /* body */
  --fe-text-lead: 16px;                             /* field values (no zoom on iOS), reading text on phones */
  --fe-text-lg: 17px;                               /* card and group titles, prominent figures */
  --fe-text-xl: clamp(21px, .6vw + 15px, 24px);     /* dialog, sheet and section titles */
  --fe-text-2xl: clamp(30px, 1.8vw + 16px, 44px);   /* screen titles: Geist medium, tight */
  --fe-text-num: 36px;                              /* data-xl */
  --fe-text-pull: 20px;                             /* a pull quote (what you tell your client) */
  --fe-text-figure: 24px;                           /* a figure that stands alone (day rate, version) */
  --fe-text-total: clamp(22px, 1.2vw + 13px, 28px); /* the quote total in the panel header */
  --fe-text-price: clamp(34px, 1.6vw + 20px, 44px); /* the hero price: result and review */
  --fe-gutter: clamp(16px, 3vw, 32px);

  --fe-ease-in-out: cubic-bezier(.65,0,.35,1);      /* loading pulse only */
  --fe-dur-1: 120ms;  /* colour: hover, press */
  --fe-dur-2: 160ms;  /* small movement */
  --fe-dur-3: 240ms;  /* panels, reveals */
  --fe-dur-4: 240ms;  /* sheets, dialogs */
  --fe-dur-hover: 420ms;  /* a large card's hover: lift, edge and arrow move together, calmly */
  --fe-dur-spin: 700ms;       /* the busy spinner, one turn */
  --fe-dur-loop: 1.2s;        /* pulse and flash */
  --fe-dur-toast: 2800ms;     /* a toast stays */
  --fe-dur-toast-act: 6000ms; /* a toast with an action stays longer */
  --fe-dur-instant: 1ms;      /* reduced motion */

  --fe-side-w: var(--sidebar-width);
  --fe-panel-w: 600px;
  --fe-safe-b: env(safe-area-inset-bottom, 0px);

  /* ---- 1c. Quote document (neutral: it carries the photographer's brand, not ours) ---- */
  --fe-doc-ink:   #1F1E1C;
  --fe-doc-ink-2: #5E5A53;
  --fe-doc-ink-3: #6B665E;
  --fe-doc-line:  #E7E2D9;
  --fe-doc-line-2:#D7D0C3;
  /* Type and space of the HTML letter (the preview's fallback; the PDF has its own metrics in core.js) */
  --doc-text-caps: 9.5px; --doc-text-xs: 10.5px; --doc-text-sm: 11.5px; --doc-text-body-s: 12.5px;
  --doc-text-body: 13.5px; --doc-text-lg: 15px; --doc-text-title: 22px;
  --doc-space-1: 3px; --doc-space-2: 6px; --doc-space-3: 10px; --doc-space-4: 14px;
  --doc-space-5: 18px; --doc-space-6: 22px; --doc-space-7: 28px; --doc-space-8: 36px;
  --fe-doc-page:  #FFFFFF;
  --fe-doc-serif: "Source Serif 4", "Iowan Old Style", Georgia, serif;
  --fe-doc-sans:  "Geist", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --fe-print-black: #000;          /* FairExposure seal: single-colour, print-safe */

  /* PDF (jsPDF cannot read CSS; core.js reads these tokens at export time) */
  --fe-pdf-ink:   #1C1B19;          /* also the default accent of a personal quote style */
  --fe-pdf-ink-2: #4E4B45;
  --fe-pdf-ink-3: #6E6A62;
  --fe-pdf-rule:  #AAA59B;
  --fe-pdf-gold:  #AF9E6E;
  --fe-pdf-mark:  #96928A;          /* fold and punch marks */

  /* ---- 1d. Component tokens (design-system components; app components: top of app.css) ---- */
  /* Switch (56 × 24 track that names its state) */
  --switch-h: 24px; --switch-knob: 18px; --switch-knob-inset: 2px; --switch-travel: 20px; --switch-w: 44px;   /* travel = w − knob − 2 × inset − 2 × hairline; inset = (h − knob − 2 × hairline) / 2, so the knob sits centred (0.9.8) */
  --range-thumb: 20px;        /* 0.9.10: the knob of a range slider (the dot in the fair band) */
  --price-field-w: 88px;      /* 0.9.10: a typed amount in a value list (up to CHF 99’995) */
  /* Badge */
  --badge-h: 22px;
  /* Toast */
  --toast-max-w: 420px;
  /* Dialog */
  --dialog-max-h: 900px; --dialog-w: 820px;
  /* Wordmark: bar and sidebar heights, fluid size on narrow top bars */
  --wordmark-h: 20px;
}
/* ---- 1e. Breakpoints (media and container queries cannot read custom properties; scripts/check-tokens.py
   allows only these widths). Viewport: 340 · 370 · 380 (tiny phones) · 520 (landscape height) · 560 · 640 (phone)
   · 680 · 720 · 899/900 · 1024/1025 (tablet ↔ desktop) · 1320/1321 (laptop ↔ wide). Containers: 280 · 430 · 460 · 480
   · 520 · 560 · 620. ---- */

/* ---------- 2. Base ---------- */
*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0; background:var(--surface); color:var(--text);
  font-family:var(--font-sans); font-size:var(--fe-text-md); line-height:var(--leading-md);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;-webkit-tap-highlight-color:transparent}
:focus-visible{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset);border-radius:0}
::selection{background:var(--accent-soft);color:var(--text)}

/* Type styles (design system names in the comments) */
.fe-label{font-family:var(--font-sans);font-size:var(--fe-text-ui);line-height:var(--leading-ui);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-ui);color:var(--text)}           /* label */
.fe-eyebrow{font-family:var(--font-sans);font-size:var(--fe-text-sm);line-height:var(--leading-sm);font-weight:var(--weight-bold);color:var(--text-muted);letter-spacing:0;text-transform:none}   /* 0.9.1: a quiet small heading in normal case, no tracked capitals */
.fe-section-label{font-family:var(--font-sans);font-size:var(--fe-text-sm);line-height:var(--leading-sm);font-weight:var(--weight-bold);letter-spacing:0;text-transform:none;color:var(--text)} /* section-label */
.fe-hint{font-family:var(--font-sans);font-size:var(--fe-text-sm);line-height:var(--leading-sm);letter-spacing:var(--tracking-ui);color:var(--text-muted);margin:0}         /* small */
.fe-num{font-family:var(--font-figures);font-variant-numeric:tabular-nums lining-nums;letter-spacing:0}                                  /* data */
.fe-sr{position:absolute!important;width:var(--size-px);height:var(--size-px);overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- 3. Brand ---------- */
/* The logo (approved, 0.8.3 / 0.8.6): the Schnittbild beside the Archivo Black wordmark; on screen the mark is kobalt
   above, koralle below, the wordmark one ink. The one-ink logo is for print. Changes need the director's approval. */
.fe-logo{display:inline-flex;flex-direction:column;align-items:flex-start;gap:var(--space-2);color:var(--text);text-decoration:none}
.fe-wordmark{display:block;flex:none;width:auto;height:var(--wordmark-h);fill:currentColor;overflow:visible}
.fe-logo .fe-tag{display:block;font-family:var(--font-sans);font-size:var(--fe-text-sm);line-height:var(--leading-sm);letter-spacing:var(--tracking-ui);color:var(--text-muted);white-space:nowrap}

/* ---------- 3b. Light: graphic elements (design system › Graphic elements) ----------
   Hues are layers in multiply at opacity-overlay, pale parts at opacity-veil. They overlap: where two
   inks meet, a third appears; they carry a fine film grain (--grain). No gradients. Never as text,
   never behind text that must be read. */
.fe-blend{mix-blend-mode:multiply;opacity:var(--opacity-overlay)}
.fe-blend.fe-veil{opacity:var(--opacity-veil)}
/* Film grain on colour layers: add .fe-grain (or list the element in app.css «Licht»); masks the layer with --grain */
.fe-grain{-webkit-mask-image:var(--grain);mask-image:var(--grain);-webkit-mask-size:var(--grain-size);mask-size:var(--grain-size)}
.fe-blend.m{fill:var(--magenta)}.fe-blend.k{fill:var(--kobalt)}.fe-blend.o{fill:var(--koralle)}.fe-blend.l{fill:var(--limette)}.fe-blend.p{fill:var(--petrol)}

/* Aperture brackets (ApertureFrame): 2px tinte, arms 24px, at two diagonal corners of a headline block */
.fe-frame{position:relative}
.fe-frame::before{content:"";position:absolute;inset:var(--frame-inset,-12px);pointer-events:none;--_a:var(--frame-arm,24px);
  background:
    linear-gradient(var(--tinte),var(--tinte)) 0 0/var(--_a) var(--stroke-mark) no-repeat,
    linear-gradient(var(--tinte),var(--tinte)) 0 0/var(--stroke-mark) var(--_a) no-repeat,
    linear-gradient(var(--tinte),var(--tinte)) 100% 100%/var(--_a) var(--stroke-mark) no-repeat,
    linear-gradient(var(--tinte),var(--tinte)) 100% 100%/var(--stroke-mark) var(--_a) no-repeat}

/* Lines: the short accent rule (32 × 2), an eyebrow running into a hairline, the tagline triad */
.fe-rule-s{display:block;width:var(--space-6);height:var(--stroke-mark);background:var(--tinte)}
.fe-ruled{display:flex;align-items:center;gap:var(--space-3)}
.fe-ruled::after{content:"";flex:1;height:var(--stroke-hairline);background:var(--line)}
.fe-tagline{margin:0;font-family:var(--font-sans);font-size:var(--fe-text-2xs);line-height:var(--leading-sm);font-weight:var(--weight-medium);letter-spacing:var(--tracking-caps);word-spacing:var(--word-spacing-caps);text-transform:uppercase;color:var(--text-muted);text-wrap:balance}

/* Steps: done and current in tinte, the rest on line-soft */
.fe-steps{display:flex;gap:var(--space-1)}
.fe-steps i{flex:1;height:var(--stroke-bar);background:var(--line-soft)}
.fe-steps i.is-done{background:var(--tinte)}
.fe-steps i.is-cur{background:var(--beam);background-blend-mode:multiply}

/* ---------- 4. Components ---------- */

/* Button: square, label type; hover = its own text colour veiled over it */
.fe-btn{
  --_bg:transparent; --_fg:var(--text); --_bd:var(--tinte);
  position:relative; isolation:isolate; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  min-height:var(--control-md); padding:0 var(--space-4); margin:0;
  border:var(--stroke-hairline) solid var(--_bd); border-radius:var(--radius-pill);   /* 0.9.1: buttons are pills */
  background:var(--_bg); color:var(--_fg); text-decoration:none;
  font-family:var(--font-sans); font-size:var(--fe-text-ui); line-height:var(--leading-ui); font-weight:var(--weight-semibold); letter-spacing:var(--tracking-ui); white-space:nowrap;
  transition:background-color var(--fe-dur-1), border-color var(--fe-dur-1), color var(--fe-dur-1), transform var(--fe-dur-1) var(--ease);
}
.fe-btn::before{content:"";position:absolute;inset:0;z-index:-1;background:currentColor;opacity:0;transition:opacity var(--fe-dur-1)}
@media (hover:hover){.fe-btn:hover::before{opacity:var(--opacity-hover)}}
.fe-btn:active::before{opacity:calc(var(--opacity-hover) * 1.6)}
.fe-btn:focus-visible{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-btn--primary{--_bg:var(--tinte);--_fg:var(--text-inverse);--_bd:var(--tinte)}
.fe-btn--ghost{--_bd:transparent}
.fe-btn--danger{--_bg:var(--danger);--_fg:var(--text-inverse);--_bd:var(--danger)}
.fe-btn--sm{min-height:var(--control-sm);padding:0 var(--space-3)}
.fe-btn--icon{width:var(--control-md);padding:0}
.fe-btn--sm.fe-btn--icon{width:var(--control-sm)}
.fe-btn[disabled]{opacity:var(--opacity-disabled);cursor:not-allowed}
.fe-btn[disabled]::before,.fe-btn--primary[disabled]::after{display:none}
/* Busy (0.8.8): the pressed action keeps its colours, ignores clicks and shows a small spinner before its label */
.fe-btn.is-busy[disabled]{opacity:1;cursor:progress}
.fe-btn.is-busy::before{display:block;position:static;inset:auto;z-index:0;flex:none;width:var(--icon-sm);height:var(--icon-sm);box-sizing:border-box;
  border:var(--stroke-mark) solid currentColor;border-right-color:transparent;border-radius:var(--radius-round);background:none;opacity:1;animation:fe-spin var(--fe-dur-spin) linear infinite}
.fe-btn.is-busy > svg{display:none}
.fe-btn svg{flex:none}

/* «Neue Offerte» (0.9.1): a calm white pill with the plus in gold; hover warms it */
.fe-new{display:inline-flex;align-items:center;min-height:var(--control-md);border-radius:var(--radius-pill);gap:var(--space-2);padding:0 var(--space-4) 0 var(--space-3);border:var(--stroke-hairline) solid var(--line-strong);background:var(--surface-raised);color:var(--text)}
.fe-new > svg{color:var(--accent-ink)}
@media (hover:hover){.fe-new:hover{background:var(--accent-soft);border-color:var(--accent-line)}}
.fe-new::before{display:none}

/* Icons: the design system's set (24px grid, 2px strokes, square caps, mitred corners) */
.fe-ico{display:inline-block;flex:none;vertical-align:middle;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter}

/* Segmented control: tinte edge, the selected segment filled in tinte */
.fe-seg{
  position:relative; display:inline-grid; grid-auto-flow:column; grid-auto-columns:1fr;
  gap:var(--space-half); padding:var(--space-half); border:0; border-radius:var(--radius-pill); background:var(--surface-active);   /* 0.9.1: a sunken track */
  font-family:var(--font-sans); font-size:var(--fe-text-ui); line-height:var(--leading-ui); font-weight:var(--weight-semibold); letter-spacing:var(--tracking-ui);
}
.fe-seg button{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  min-height:calc(var(--control-md) - var(--space-half)); padding:0 var(--space-4); margin:0;
  border:0; border-radius:var(--radius-pill);
  background:transparent; color:var(--text-muted); white-space:nowrap;
  transition:background-color var(--fe-dur-1), color var(--fe-dur-1), box-shadow var(--fe-dur-1);
}
.fe-seg button:first-child{border-left:0}
@media (hover:hover){.fe-seg button:hover{background:var(--surface-hover)}}
.fe-seg button[aria-pressed="true"],.fe-seg button[aria-selected="true"]{background:var(--surface-raised);color:var(--text);box-shadow:var(--shadow-knob)}   /* the chosen segment is a white knob */
.fe-seg button:focus-visible{position:relative;z-index:1}
/* 0.9.8: the knob slides. Once positionSegs() has measured the chosen segment (--_x, --_w), a single knob (::before) moves
   to it like a physical slider instead of the segment switching its own background. Without JS the segment itself is the knob. */
.fe-seg[data-seg].is-slide::before{content:"";position:absolute;top:var(--space-half);bottom:var(--space-half);left:0;width:var(--_w);transform:translateX(var(--_x));border-radius:var(--radius-pill);background:var(--surface-raised);box-shadow:var(--shadow-knob);transition:transform var(--fe-dur-3) var(--ease), width var(--fe-dur-3) var(--ease)}
.fe-seg[data-seg].is-slide button{position:relative;z-index:1}
.fe-seg[data-seg].is-slide button[aria-pressed="true"],.fe-seg[data-seg].is-slide button[aria-selected="true"]{background:transparent;box-shadow:none}
@media (prefers-reduced-motion:reduce){.fe-seg[data-seg].is-slide::before{transition:none}}
.fe-seg--sm button{min-height:calc(var(--control-sm) - var(--space-half));padding:0 var(--space-3)}

/* Chips (radio and checkbox choices): square, line-strong edge, tinte when chosen; a plus turns into a check */
.fe-pills{display:flex;flex-wrap:wrap;gap:var(--space-2)}
.fe-pill{position:relative;display:inline-flex}
.fe-pill input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}
.fe-pill span{
  display:inline-flex; align-items:center; gap:var(--space-2); min-height:var(--control-md); padding:0 var(--space-4);
  font-family:var(--font-sans); font-size:var(--fe-text-ui); line-height:var(--leading-ui); font-weight:var(--weight-semibold); letter-spacing:var(--tracking-ui);
  border:var(--stroke-hairline) solid var(--line-strong); border-radius:var(--radius-pill); background:var(--surface-raised); color:var(--text);
  transition:background-color var(--fe-dur-1), border-color var(--fe-dur-1), color var(--fe-dur-1), transform var(--fe-dur-1) var(--ease);
}
@media (hover:hover){.fe-pill:hover span{border-color:var(--tinte)}}
@media (hover:hover){.fe-pill:hover input:not(:checked) + span{background:var(--surface-hover)}}
.fe-pill input:checked + span{position:relative;background:var(--tinte);border-color:var(--tinte);color:var(--text-inverse)}
.fe-pill input[type=checkbox] + span::before{
  content:""; flex:none; width:var(--icon-sm); height:var(--icon-sm); margin-left:calc(var(--space-1) * -1); background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5V19M5 12H19'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5V19M5 12H19'/%3E%3C/svg%3E") center/contain no-repeat;
}
.fe-pill input[type=checkbox]:checked + span::before{
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12.5L10 17.5L19 7'/%3E%3C/svg%3E");
          mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12.5L10 17.5L19 7'/%3E%3C/svg%3E");
}
.fe-pill input:focus-visible + span{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-pill input:disabled + span{opacity:var(--opacity-disabled);cursor:not-allowed}

/* Fields: square, 40px, line-strong edge; hover tinte; focus kobalt edge + inner ring */
.fe-field{display:flex;flex-direction:column;gap:var(--space-2);min-width:0}
.fe-input{
  width:100%; min-width:0; min-height:var(--control-md); padding:0 var(--space-3);
  border:var(--stroke-hairline) solid var(--line-strong); border-radius:var(--radius-control); background:var(--surface-raised);
  font-family:var(--font-sans); font-size:var(--fe-text-lead); line-height:var(--leading-md); color:var(--text);
  transition:border-color var(--fe-dur-1), box-shadow var(--fe-dur-1);
}
.fe-input::placeholder{color:var(--text-subtle);opacity:1}
@media (hover:hover){.fe-input:hover{border-color:var(--tinte)}}
.fe-input:focus{outline:none;border-color:var(--focus);box-shadow:0 0 0 var(--stroke-hairline) var(--focus)}
.fe-input[aria-invalid="true"]{border-color:var(--danger)}
.fe-input[aria-invalid="true"]:focus{box-shadow:0 0 0 var(--stroke-hairline) var(--danger)}
.fe-input:disabled{opacity:var(--opacity-disabled);background:var(--surface);cursor:not-allowed}
select.fe-input{appearance:none;-webkit-appearance:none;padding-right:calc(var(--space-3) + var(--icon-md) + var(--space-1));cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23111111' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M6 9L12 15L18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--space-3) center;background-size:var(--icon-md)}
textarea.fe-input{resize:vertical;min-height:var(--space-9);padding:var(--space-3);line-height:var(--leading-md)}

/* Stepper (number with − and +) */
.fe-stepper{display:flex;align-items:center;min-height:var(--control-md);border:var(--stroke-hairline) solid var(--line-strong);border-radius:var(--radius-control);background:var(--surface-raised);overflow:hidden;transition:border-color var(--fe-dur-1), box-shadow var(--fe-dur-1)}
@media (hover:hover){.fe-stepper:hover{border-color:var(--tinte)}}
.fe-stepper:focus-within{border-color:var(--focus);box-shadow:0 0 0 var(--stroke-hairline) var(--focus)}
.fe-stepper button{flex:none;display:flex;align-items:center;justify-content:center;width:var(--control-md);align-self:stretch;border:0;border-radius:var(--radius-control);background:transparent;color:var(--text);font-size:0;line-height:var(--leading-none);transition:background-color var(--fe-dur-1)}
.fe-stepper button::before{content:"";width:var(--icon-md);height:var(--icon-md);background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5V19M5 12H19'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M12 5V19M5 12H19'/%3E%3C/svg%3E") center/contain no-repeat}   /* − and + from the icon set, not text glyphs */
.fe-stepper button[data-step^="-"]::before{-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12H19'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M5 12H19'/%3E%3C/svg%3E")}
@media (hover:hover){.fe-stepper button:hover{background:var(--surface-hover)}}
.fe-stepper button:active{background:var(--surface-active)}
.fe-stepper button:disabled{opacity:var(--opacity-disabled);cursor:not-allowed;background:transparent}
.fe-stepper input{flex:1;min-width:0;width:100%;border:0;background:transparent;text-align:center;padding:var(--space-2) 0;-moz-appearance:textfield}
.fe-stepper input:focus{outline:none}
.fe-stepper input::-webkit-outer-spin-button,.fe-stepper input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.fe-stepper .fe-unit{font-family:var(--font-sans);font-size:var(--fe-text-sm);font-weight:var(--weight-medium);color:var(--text-muted);padding-right:var(--space-2)}
.fe-stepper:has(.fe-unit) input{text-align:right;padding-right:var(--space-2)}   /* value and unit read as one: «0 %» */
.fe-stepper.is-bumped input{animation:fe-bump var(--fe-dur-3) var(--ease)}

/* Switch (0.8.8): a square 56 × 24 track that names its state, so it never reads as a checkbox.
   Off: an empty track, the knob on the left in line-strong, «Aus» / «Off» on the right in muted capitals.
   On: the track in tinte, the knob on the right in warmweiss, «An» / «On» on the left.
   The word follows the page language (html lang); screen readers get the checkbox state, the <i> is aria-hidden. */
/* Range (0.9.10): a coral knob on a quiet track; the knob lifts a little under the pointer */
.fe-range{-webkit-appearance:none;appearance:none;display:block;width:100%;height:var(--control-touch);margin:0;background:transparent;cursor:pointer;touch-action:pan-y}
.fe-range::-webkit-slider-runnable-track{height:var(--stroke-mark);border-radius:var(--radius-pill);background:var(--line-strong)}
.fe-range::-moz-range-track{height:var(--stroke-mark);border-radius:var(--radius-pill);background:var(--line-strong)}
.fe-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:var(--range-thumb);height:var(--range-thumb);margin-top:calc((var(--range-thumb) - var(--stroke-mark)) / -2);border:0;border-radius:var(--radius-round);background:var(--koralle);box-shadow:0 0 0 var(--stroke-mark) var(--surface-raised),var(--shadow-knob);transition:transform var(--fe-dur-2) var(--ease)}
.fe-range::-moz-range-thumb{width:var(--range-thumb);height:var(--range-thumb);border:0;border-radius:var(--radius-round);background:var(--koralle);box-shadow:0 0 0 var(--stroke-mark) var(--surface-raised),var(--shadow-knob);transition:transform var(--fe-dur-2) var(--ease)}
@media (hover:hover){.fe-range:hover::-webkit-slider-thumb{transform:scale(1.1)}.fe-range:hover::-moz-range-thumb{transform:scale(1.1)}}
.fe-range:active::-webkit-slider-thumb{transform:scale(1.15)}
.fe-range:active::-moz-range-thumb{transform:scale(1.15)}
.fe-range:focus-visible{outline:0}
.fe-range:focus-visible::-webkit-slider-thumb{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-range:focus-visible::-moz-range-thumb{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-switch{position:relative;width:var(--switch-w);height:var(--switch-h);flex:none}
.fe-switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:1}
@media (pointer:coarse){.fe-switch input{inset:calc(var(--space-3) * -1) calc(var(--space-1) * -1)}}
/* 0.8.9 (H5): a standard switch — a rounded track (the one exception to square: the shape is the affordance), a knob that
   slides, the state by position and ink fill. The row's title names it; no «Aus»/«An» text inside. */
.fe-switch i{position:absolute;inset:0;border:var(--stroke-hairline) solid var(--line-strong);border-radius:var(--radius-pill);background:var(--surface-active);transition:background-color var(--fe-dur-2), border-color var(--fe-dur-2)}
.fe-switch i::after{content:"";position:absolute;top:var(--switch-knob-inset);left:var(--switch-knob-inset);width:var(--switch-knob);height:var(--switch-knob);border-radius:var(--radius-round);background:var(--surface-raised);box-shadow:0 0 0 var(--stroke-hairline) var(--line-strong);transition:transform var(--fe-dur-2) var(--ease), background-color var(--fe-dur-2), box-shadow var(--fe-dur-2)}
@media (hover:hover){.fe-switch:hover i{border-color:var(--tinte)}}
.fe-switch input:checked + i{background:var(--tinte);border-color:var(--tinte)}
.fe-switch input:checked + i::after{background:var(--warmweiss);box-shadow:none;transform:translateX(var(--switch-travel))}
.fe-switch input:focus-visible + i{outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-switch input:disabled + i{opacity:var(--opacity-disabled)}
.fe-switch input:disabled{cursor:not-allowed}

/* Toggle row: a switch with its label on a card. 0.8.8: the whole row is the switch's hit area
   (the input stretches over the row), hover and the focus ring belong to the row. */
.fe-toggle{position:relative;display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);padding:var(--space-3) var(--space-4);border:var(--stroke-hairline) solid var(--line-soft);border-radius:var(--radius-card);background:var(--surface-raised);transition:border-color var(--fe-dur-1)}
.fe-toggle .tl{display:flex;flex-direction:column;gap:var(--space-half);min-width:0}
.fe-toggle .tl b{font-weight:var(--weight-semibold);font-size:var(--fe-text-md);line-height:var(--leading-md)}
.fe-toggle .tl small{font-size:var(--fe-text-sm);line-height:var(--leading-sm);color:var(--text-muted)}
.fe-toggle .fe-switch{position:static}
.fe-toggle .fe-switch i{position:relative;display:block;width:var(--switch-w);height:var(--switch-h)}
.fe-toggle .fe-switch input{inset:0}
@media (hover:hover){.fe-toggle:has(input:not(:disabled)):hover{border-color:var(--tinte)}.fe-toggle:hover .fe-switch i{border-color:var(--tinte)}}
.fe-toggle:has(.fe-switch input:focus-visible){outline:var(--stroke-mark) solid var(--focus);outline-offset:var(--focus-offset)}
.fe-toggle .fe-switch input:focus-visible + i{outline:none}
.fe-toggle:has(.fe-switch input:disabled){cursor:not-allowed}

/* Card: surface-raised, a line-soft edge, radius-card, no shadow */
.fe-card{background:var(--surface-raised);border:var(--stroke-hairline) solid var(--line-soft);border-radius:var(--radius-card)}

/* Alert (info): kobalt tint, the icon in info, text in ink */
.fe-tip{display:flex;gap:var(--space-3);align-items:flex-start;padding:var(--space-4);background:var(--info-tint);color:var(--text);font-family:var(--font-sans);font-size:var(--fe-text-ui);line-height:var(--leading-ui)}
.fe-tip svg{flex:none;color:var(--info)}

/* Badge: square, 22px; neutral (line-strong edge) or limette (news, Beta) */
.fe-badge{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1);min-width:var(--badge-h);height:var(--badge-h);padding:0 var(--space-2);border:var(--stroke-hairline) solid var(--line-strong);border-radius:var(--radius-control);background:transparent;color:var(--text);font-family:var(--font-sans);font-size:var(--fe-text-xs);line-height:var(--leading-xs);font-weight:var(--weight-semibold);letter-spacing:var(--tracking-ui)}
.fe-badge--gold{text-transform:none!important;letter-spacing:var(--tracking-ui)!important}   /* «Beta»: one neutral badge everywhere */

/* Toast: tinte, bottom centre on phones and tablets, bottom right on desktop; the check in petrol */
.fe-toast{
  position:fixed; left:50%; bottom:calc(var(--space-9) + var(--fe-safe-b)); z-index:var(--z-toast);
  display:flex; align-items:center; gap:var(--space-3); width:max-content; max-width:min(var(--toast-max-w), calc(100% - var(--space-6)));
  padding:var(--space-3) var(--space-4) var(--space-3) var(--space-3); border-radius:var(--radius-control);
  background:var(--tinte); color:var(--text-inverse); font-family:var(--font-sans); font-size:var(--fe-text-ui); line-height:var(--leading-ui); font-weight:var(--weight-medium);
  translate:-50% var(--space-3); opacity:0; pointer-events:none;
  transition:translate var(--fe-dur-3) var(--ease), opacity var(--fe-dur-2) var(--ease);
}
.fe-toast::before{content:"";width:var(--icon-md);height:var(--icon-md);flex:none;background:var(--petrol);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5L11 15.5L16.5 9.5'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='square'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5L11 15.5L16.5 9.5'/%3E%3C/svg%3E") center/contain no-repeat}
.fe-toast.is-on{translate:-50% 0;opacity:1}
.fe-toast::after{content:"";position:absolute;left:0;right:0;bottom:0;height:var(--stroke-bar);background:var(--text-inverse);opacity:var(--opacity-veil);transform-origin:left;transform:scaleX(0);pointer-events:none}   /* an ink line runs down with the time left */
.fe-toast.is-on::after{animation:fe-time var(--fe-dur-toast) linear both}
.fe-toast.is-on.has-act::after{animation-duration:var(--fe-dur-toast-act)}
@keyframes fe-time{from{transform:scaleX(1)}to{transform:scaleX(0)}}
@media (min-width:1025px){
  .fe-toast{left:auto;right:var(--space-5);bottom:var(--space-5);translate:0 var(--space-3)}
  .fe-toast.is-on{translate:0 0}
}

/* Dialog: surface-raised panel, line-soft edge, radius-card, over the tinte scrim */
.fe-scrim{position:fixed;inset:0;background:var(--scrim);z-index:var(--z-scrim);animation:fe-fade var(--fe-dur-3) var(--ease) both}
.fe-dialog{
  position:fixed; left:50%; top:50%; translate:-50% -50%; z-index:var(--z-dialog);
  width:min(var(--dialog-w), calc(100% - var(--space-5))); max-height:min(88dvh, var(--dialog-max-h));
  background:var(--surface-raised); border:var(--stroke-hairline) solid var(--line-soft); border-radius:var(--radius-card);
  display:flex; flex-direction:column; overflow:hidden;
  animation:fe-pop var(--fe-dur-4) var(--ease) both;
}
.fe-scrim.is-leaving{animation:fe-fade var(--fe-dur-2) var(--ease) reverse both}
.fe-dialog.is-leaving{animation:fe-pop-out var(--fe-dur-2) var(--ease) both}

/* ---------- 5. Motion primitives ---------- */
@keyframes fe-fade{from{opacity:0}to{opacity:1}}
@keyframes fe-rise{from{opacity:0;transform:translateY(var(--space-2))}to{opacity:1;transform:none}}
@keyframes fe-pop{from{opacity:0;scale:.98}to{opacity:1;scale:1}}
@keyframes fe-pop-out{from{opacity:1;scale:1}to{opacity:0;scale:.98}}
@keyframes fe-bump{0%{transform:none}40%{transform:translateY(calc(var(--space-half) * -1))}100%{transform:none}}
@keyframes fe-flash{0%{background-color:var(--surface-active)}100%{background-color:transparent}}
@keyframes fe-pulse{0%,100%{opacity:1}50%{opacity:var(--opacity-pulse)}}
@keyframes fe-spin{to{rotate:360deg}}

.fe-flash{animation:fe-flash var(--fe-dur-loop) var(--ease)}

/* View transitions (mode and tab changes) */
/* Only the quote panel cross-fades; the rest of the page stays live */
:root{view-transition-name:none}
::view-transition-group(fe-doc){animation-duration:var(--fe-dur-3);animation-timing-function:var(--ease)}
::view-transition-old(fe-doc),::view-transition-new(fe-doc){animation-duration:var(--fe-dur-2);animation-timing-function:var(--ease)}

/* ---------- 6. Reduced motion ---------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:var(--fe-dur-instant)!important;animation-delay:0ms!important;animation-iteration-count:1!important;transition-duration:var(--fe-dur-instant)!important;scroll-behavior:auto!important}
}
@media (prefers-reduced-motion: reduce){.fe-toast.is-on::after{animation:none;transform:none}}   /* a still line instead of a running one */

/* ---------- Numbers: IBM Plex Mono, tabular ---------- */
.fe-stepper input,
input[type=number].fe-input,
input[type=date].fe-input,
.kv input[type=number]{
  font-family:var(--font-figures); font-size:var(--fe-text-lead); font-weight:var(--weight-medium); letter-spacing:0;
  font-variant-numeric:tabular-nums lining-nums;
  color:var(--text);
}
.kv input[type=number]{font-size:var(--fe-text-md)}
