/* Smartwave design tokens — v2.
 *
 * Layers 1 and 2 of docs/design-system.md, verbatim. That document is the source of truth: a
 * value that is not there does not exist, and a token added here without being added there is
 * a defect (design-system.md §10 rule 9).
 *
 * This is also one of the two client-specific surfaces named in ADR-0010. Keeping it the single
 * point of change is what makes that claim true, which is why both layers live in one file
 * rather than two.
 *
 * THE LAYER BOUNDARY BELOW IS PARSED BY A TEST. The LAYER 1 sentinels delimit the set of names
 * that no stylesheet outside this file may reference; DesignTokenLayerTests reads them from
 * here rather than carrying its own copy, because a hardcoded list rots silently the first time
 * somebody adds a primitive. Do not reword or remove the sentinel lines.
 *
 * There is no structural enforcement available here, and none is claimed. Every custom property
 * declared on :root is global and reachable from every rule in every stylesheet; CSS has no
 * scoping mechanism for them. See ADR-0005.
 *
 * ==============================================================================================
 * V2 — DARK SHIPS, AND light-dark() IS HOW IT SHIPS WITHOUT A SECOND COPY OF THE PALETTE.
 *
 * Every theme-varying alias below is written ONCE, as light-dark(light, dark), with a Layer 1
 * primitive on each side. The alternative - a [data-theme="dark"] block repeating forty aliases -
 * is forty chances for the two lists to drift, and drift in a palette is invisible until somebody
 * screenshots the wrong theme.
 *
 * It works because `color-scheme` decides which half is used, and `color-scheme` is inheritable
 * and overridable per subtree. So:
 *   - the page follows the operating system, via `color-scheme: light dark` in base.css;
 *   - [data-theme="dark"] / [data-theme="light"] force a subtree, which is what lets
 *     /design-system show both themes side by side on one page;
 *   - and the same attributes are what a persisted per-user toggle will set later, on <html>.
 *
 * Baseline newly available since May 2024 (Chrome 123, Safari 17.5, Firefox 120).
 * https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark
 *
 * WHAT IS NOT WRAPPED, and why: light-dark() takes COLOURS. A gradient, a shadow list and a size
 * are not colours, so where those vary by theme the COLOUR inside them is the token that varies.
 * That is why --color-shadow-* exists and --shadow-* composes from it.
 * ============================================================================================== */

/* ===== LAYER 1 — PRIMITIVES. Never referenced outside this file. ===== */
:root {
  /* ---- Green (institutional) ----
   *
   * 300 and 400 are NEW IN V2 AND EXIST FOR DARK. #176D44 on a near-black panel is a 1.9:1 shape:
   * legible as text nowhere and failing SC 1.4.11 as a control boundary. A filled action on dark
   * needs a LIGHTER green carrying DARK text, which is 400; a link or a focus ring on dark needs a
   * lighter one still, which is 300. DERIVED - needs sign-off. */
  --color-primary-50:  #EDF7F1;
  --color-primary-100: #D8EBDD;
  --color-primary-300: #5FC48F;  /* DERIVED — links, focus, accents on dark */
  --color-primary-400: #34A96F;  /* DERIVED — filled actions on dark, carries dark text */
  --color-primary-600: #176D44;  /* brand: Verde Novofarlab */
  --color-primary-700: #145F3C;
  --color-primary-800: #0F4D32;  /* brand: Verde profundo */
  --color-primary-900: #0A3823;  /* DERIVED — dark-mode headroom, needs sign-off */

  /* ---- Teal (secondary / informational) ----
   *
   * V2 PROMOTES TEAL FROM DECORATION TO A WORKING ACCENT. The palette read as monochrome green
   * because nothing but green was ever used; 100 and 300 are the tints that let a KPI chip or an
   * informational highlight be teal without inventing a hue. DERIVED.
   *
   * -900 REPLACED -700 AS THE DARK CHIP SURFACE, AND THE AXE SWEEP IS WHAT FOUND IT. Teal was the
   * only tone whose dark background was a MID-tone: every other tone and status background on dark
   * is a near-black -900, and #7FBCC8 on #2A565F measures 3.83:1 — fine for a shape, a failure for
   * the text the chip's own sibling (.sw-chip) proves these tokens carry. The anomaly was the
   * value, not the ratio, so the fix is the missing step rather than a lighter foreground: #0B2126
   * is a teal near-black whose luminance (0.0130) sits with success-900, info-900 and warning-900
   * (0.0102–0.0112) instead of two ramps above them. Measured 7.88:1. §9. */
  --color-secondary-50:  #EEF4F5;  /* DERIVED */
  --color-secondary-100: #D5E4E7;  /* DERIVED — teal chip on light */
  --color-secondary-300: #7FBCC8;  /* DERIVED — teal on dark */
  --color-secondary-600: #356C77;  /* brand: Azul petróleo */
  --color-secondary-900: #0B2126;  /* DERIVED — teal chip surface on dark */

  /* ---- Amber (accent) ---- */
  --color-accent-100: #F6E8CC;  /* DERIVED — amber chip on light */
  --color-accent-300: #E2B460;  /* DERIVED — amber on dark */
  --color-accent-500: #C28A2B;  /* brand: Ámbar sobrio — NON-TEXT USE ONLY, 3.0:1 on white */
  --color-accent-700: #8A5A00;  /* text-safe amber, 5.9:1 on white */

  /* ---- Neutrals ----
   *
   * THE DARK RAMP IS NEW AND IS NOT THE LIGHT ONE INVERTED. Dark surfaces are a green-tinted
   * charcoal rather than a pure grey, so the brand's hue survives into the dark theme instead of
   * the product looking like a different application at night. Every value 775 and above is
   * DERIVED and needs sign-off. */
  --color-neutral-0:   #FFFFFF;  /* brand: Superficie blanca */
  --color-neutral-25:  #F6F8F7;  /* brand: Fondo base */

  /* 30 AND 40 ARE THE RECALIBRATION, AND THEY ARE A WHISPER OF BRAND RATHER THAN A RETURN OF IT.
   * The v2 spike neutralised the chrome correctly and then over-corrected: a pure-white sidebar on
   * a near-white page reads as stark, and the product lost the warmth of the approved direction
   * without gaining anything ADR-0030 asked for. These two are the SAME green-tinted family as the
   * rest of the ramp, one step warmer than white, and they change no rule - green still owns no
   * surface, because a neutral tinted toward the brand hue is not the brand colour. DERIVED. */
  --color-neutral-30:  #F3F7F5;  /* DERIVED — navigation surface on light */
  --color-neutral-40:  #F1F6F3;  /* DERIVED — page surface on light */

  --color-neutral-50:  #EDF2EF;  /* brand: Fondo alternativo */
  --color-neutral-100: #E9EFEB;  /* DERIVED — primary text on dark */
  --color-neutral-200: #D6DFDA;  /* brand: Borde suave */
  --color-neutral-300: #A7B6AE;  /* DERIVED — secondary text on dark */
  --color-neutral-500: #7C8983;  /* brand: Borde fuerte */
  --color-neutral-600: #5F6D66;  /* brand: Texto secundario */
  --color-neutral-775: #3A4A42;  /* DERIVED — strong border on dark */
  --color-neutral-825: #2C3A33;  /* DERIVED — hover surface on dark */
  --color-neutral-875: #232F29;  /* DERIVED — secondary surface on dark */
  --color-neutral-900: #24302B;  /* brand: Texto principal */
  --color-neutral-925: #1B2620;  /* DERIVED — panel surface on dark */
  --color-neutral-950: #17201C;  /* DERIVED — dark-mode base, needs sign-off */

  /* THE DARK CHROME SITS BETWEEN THE PAGE AND THE PANEL, which is the same hierarchy the light
   * theme now states: the navigation is not the page and not a panel, so it is neither of their
   * colours. Measured L=0.0115, between page (0.0077) and panel (0.0172). DERIVED. */
  --color-neutral-960: #141E19;  /* DERIVED — navigation surface on dark */

  --color-neutral-975: #101713;  /* DERIVED — page surface on dark */

  /* ---- Status hues ----
   *
   * FOUR STEPS PER HUE IN V2, and each has one job.
   *   -50   soft tint, alert background on light
   *   -400  NEW: the badge fill on dark, and the alert foreground on dark. Light enough to carry
   *         dark text and to clear 3:1 as a shape against a near-black panel.
   *   -600  the text colour on light, and the badge fill on light, where it carries WHITE
   *   -900  NEW: the alert background on dark
   * DERIVED except the -600/-50 pairs, which shipped in v1. */
  --color-success-600: #1F7A4D;  --color-success-50: #EEFCF5;
  --color-success-400: #2E9C67;  --color-success-900: #0A1F14;
  --color-info-600:    #2F6B9A;  --color-info-50:    #EEF6FC;
  --color-info-400:    #4C90C4;  --color-info-900:    #0B1B29;
  --color-warning-700: #8A5A00;  --color-warning-50: #FCF7EE;
  --color-warning-400: #C08A2E;  --color-warning-900: #241A05;
  --color-error-600:   #B42318;  --color-error-50:   #FCEFEE;
  --color-error-400:   #E0655A;  --color-error-900:   #2B1010;
  --color-pending-600: #5C4AB8;  --color-pending-50: #F0EDFC;
  --color-pending-400: #9186E0;  --color-pending-900: #191430;
  --color-inactive-600:#59645F;  --color-inactive-50:#F3F7F5;
  --color-inactive-400:#8A9992;  --color-inactive-900:#1A211E;

  /* ---- Shadow ink ----
   *
   * NOT A SURFACE COLOUR AND NOT A BORDER. Elevation on a light theme is a soft green-black at low
   * alpha; on a dark theme a shadow of the same ink is invisible, because there is nothing lighter
   * beneath it to darken. Dark elevation is therefore near-black at HIGH alpha, and the depth comes
   * from the surface steps as much as from the shadow. Two inks per theme - ambient and key - which
   * is what makes a layered shadow read as depth rather than as a smudge. */
  --color-shadow-ambient-light: rgb(36 48 43 / 0.06);
  --color-shadow-key-light:     rgb(36 48 43 / 0.10);
  --color-shadow-ambient-dark:  rgb(0 0 0 / 0.44);
  --color-shadow-key-dark:      rgb(0 0 0 / 0.56);

  /* ---- Overlay ink ---- */
  --color-overlay-light: rgb(36 48 43 / 0.48);
  --color-overlay-dark:  rgb(0 0 0 / 0.68);

  /* ---- Navigation ink on dark chrome ---- */
  --color-navigation-border-light: rgb(36 48 43 / 0.10);
  --color-navigation-border-dark:  rgb(255 255 255 / 0.10);

  /* ---- Chart series ---- */
  --color-chart-1: #176D44;
  --color-chart-2: #356C77;
  --color-chart-3: #6A5FA8;
  --color-chart-4: #B7991F;
  --color-chart-5: #4F6B8A;
  --color-chart-6: #A34F6F;
  --color-chart-7: #6B7280;
}
/* ===== END LAYER 1 ===== */

/* ===== LAYER 2 — SEMANTIC ALIASES. This is what components consume. =====
 *
 * ONE RULE, BOTH THEMES. See the header for why light-dark() rather than a second block.
 */
:root {
  /* ---- Surfaces ----
   *
   * NEUTRAL, AND THAT IS THE CALIBRATION V2 EXISTS FOR. Green owns actions, the mark, the active
   * navigation item, the focus ring and selection. It owns no surface. A green top bar, a green
   * table header or a green panel header reads as the brand shouting rather than signing, which is
   * exactly what "not invasive" rules out. */
  --color-surface-page:      light-dark(var(--color-neutral-40),  var(--color-neutral-975));
  --color-surface-primary:   light-dark(var(--color-neutral-0),   var(--color-neutral-925));
  --color-surface-secondary: light-dark(var(--color-neutral-50),  var(--color-neutral-875));
  --color-surface-raised:    light-dark(var(--color-neutral-0),   var(--color-neutral-875));
  --color-surface-hover:     light-dark(var(--color-neutral-50),  var(--color-neutral-825));
  --color-surface-selected:  light-dark(var(--color-primary-50),  var(--color-primary-900));

  /* The ground a product photograph sits on. A SEPARATE ALIAS RATHER THAN --color-surface-secondary,
   * and the reason is that it is the one surface in the system whose job is to stay the same in both
   * themes. The catalogue photographs are shot on white; painting a dark tile behind one draws a
   * bright square inside a dark frame, which reads as a rendering fault rather than as a photograph.
   * So it stays light in dark mode ON PURPOSE - the only light-dark() pair here that barely moves -
   * and it is named for what it holds so nobody "fixes" it into agreement with the others later. */
  --color-surface-image:     light-dark(var(--color-neutral-0),   var(--color-neutral-50));

  /* ---- Text ---- */
  --color-text-primary:       light-dark(var(--color-neutral-900), var(--color-neutral-100));
  --color-text-secondary:     light-dark(var(--color-neutral-600), var(--color-neutral-300));
  --color-text-disabled:      light-dark(var(--color-neutral-500), var(--color-neutral-500));
  --color-text-link:          light-dark(var(--color-primary-600), var(--color-primary-300));

  /* WHAT SITS ON A FILLED ACTION, AND IT FLIPS. On light the primary button is deep green and the
   * label is white. On dark the button is a LIGHT green - it has to be, to clear 3:1 as a shape
   * against a near-black panel - and white on it measures about 3.4:1, which fails. So the label
   * goes dark. A theme that reused white here would ship an unreadable primary button. */
  --color-text-on-action:     light-dark(var(--color-neutral-0),   var(--color-neutral-975));

  /* The navigation is a neutral surface in both themes now, so this is ordinary primary text. */
  --color-text-on-navigation: light-dark(var(--color-neutral-900), var(--color-neutral-100));

  /* What sits on a SOLID status pill. White on light; near-black on dark, for the same reason as
   * --color-text-on-action. */
  --color-text-on-status:     light-dark(var(--color-neutral-0),   var(--color-neutral-975));

  /* ---- Borders ---- */
  --color-border-subtle: light-dark(var(--color-neutral-200), var(--color-neutral-825));

  /* NOT THEMED, AND THE FACT THAT IT IS NOT IS THE FINDING. This was
   * light-dark(neutral-500, neutral-775) and the dark half measured 1.66:1 against the panel it
   * bounds — an input whose border a sighted user cannot locate, failing SC 1.4.11 outright. It
   * looked right because every neighbouring token flips, and "dark surfaces get a dark border" is
   * the intuition the whole ramp is built on. It is wrong for exactly the tokens that must contrast
   * with the surface rather than belong to it.
   *
   * neutral-500 clears 3:1 against ALL FOUR dark surfaces (page 4.99, primary 4.29, secondary 3.82,
   * hover 3.27) as well as against white, so one mid-grey serves both themes and no new value was
   * invented. Written as a plain var rather than light-dark(x, x) so that the absence of a flip
   * reads as a decision instead of an oversight. §9. */
  --color-border-strong: var(--color-neutral-500);

  --color-border-focus:  light-dark(var(--color-primary-600), var(--color-primary-300));

  /* ---- Actions ---- */
  --color-action-primary:        light-dark(var(--color-primary-600), var(--color-primary-400));
  --color-action-primary-hover:  light-dark(var(--color-primary-700), var(--color-primary-300));
  --color-action-primary-active: light-dark(var(--color-primary-800), var(--color-primary-400));

  --color-action-secondary-border: light-dark(var(--color-primary-600), var(--color-primary-300));
  --color-action-secondary-hover:  light-dark(var(--color-primary-50),  var(--color-primary-900));

  /* NEW IN V2 — the secondary button's pressed state, which §11 item 15 recorded as missing. It
   * had no Layer 2 alias, so pressing a secondary button produced exactly the same colour as
   * hovering it. This is the step darker §8.1's table always asked for. */
  --color-action-secondary-active: light-dark(var(--color-primary-100), var(--color-primary-800));

  --color-action-destructive:       light-dark(var(--color-error-600), var(--color-error-400));
  --color-action-destructive-hover: light-dark(#96200F, var(--color-error-600));  /* DERIVED */

  --color-action-disabled-bg:   light-dark(var(--color-neutral-200), var(--color-neutral-825));
  --color-action-disabled-text: light-dark(var(--color-neutral-600), var(--color-neutral-500));

  /* ---- Overlay ----
   *
   * WHAT SITS BETWEEN A MODAL AND THE PAGE. Promoted from --sw-drawer-scrim on 2026-08-07, which is
   * the moment design-system.md §11 item 7 named in advance. It is an accessibility affordance
   * rather than decoration: MDN's guidance on `inert` is that nothing visually distinguishes inert
   * content and indicating it is the author's job.
   *
   * Heavier on dark, because a 48% scrim over a near-black page is barely a change. */
  --color-overlay: light-dark(var(--color-overlay-light), var(--color-overlay-dark));

  /* ---- Navigation ----
   *
   * NEUTRAL CHROME IN BOTH THEMES, AND THIS IS THE BIGGEST SINGLE CHANGE IN V2. The sidebar was
   * --color-primary-800: a full-height slab of brand green, which is the definition of wallpaper.
   * It is a panel surface now, and the ONLY green in the navigation is the item you are on. */
  --color-navigation-background:  light-dark(var(--color-neutral-30), var(--color-neutral-960));
  --color-navigation-item:        light-dark(var(--color-neutral-600), var(--color-neutral-300));
  --color-navigation-item-hover:  light-dark(var(--color-neutral-50),  var(--color-neutral-825));
  --color-navigation-item-active: light-dark(var(--color-primary-50),  var(--color-primary-900));
  --color-navigation-border:      light-dark(var(--color-navigation-border-light), var(--color-navigation-border-dark));

  /* ---- Status: three roles per tone ----
   *
   * fg / bg   the SOFT pair. Alerts, and any place a tone has to sit under body text.
   * solid     NEW IN V2 — the pill. §11 item 20 measured the -50 tint at about 1.06:1 against a
   *           white panel: the badge was a coloured word with an invisible pill around it. A badge
   *           has to read at a glance down a column of forty rows, so it is now a FILLED shape
   *           carrying --color-text-on-status. Alerts keep the soft pair; they are a paragraph, and
   *           a solid red paragraph is a different and worse component.
   */
  --color-status-success-fg:    light-dark(var(--color-success-600), var(--color-success-400));
  --color-status-success-bg:    light-dark(var(--color-success-50),  var(--color-success-900));
  --color-status-success-solid: light-dark(var(--color-success-600), var(--color-success-400));

  --color-status-info-fg:    light-dark(var(--color-info-600), var(--color-info-400));
  --color-status-info-bg:    light-dark(var(--color-info-50),  var(--color-info-900));
  --color-status-info-solid: light-dark(var(--color-info-600), var(--color-info-400));

  --color-status-warning-fg:    light-dark(var(--color-warning-700), var(--color-warning-400));
  --color-status-warning-bg:    light-dark(var(--color-warning-50),  var(--color-warning-900));
  --color-status-warning-solid: light-dark(var(--color-warning-700), var(--color-warning-400));

  --color-status-error-fg:    light-dark(var(--color-error-600), var(--color-error-400));
  --color-status-error-bg:    light-dark(var(--color-error-50),  var(--color-error-900));
  --color-status-error-solid: light-dark(var(--color-error-600), var(--color-error-400));

  --color-status-pending-fg:    light-dark(var(--color-pending-600), var(--color-pending-400));
  --color-status-pending-bg:    light-dark(var(--color-pending-50),  var(--color-pending-900));
  --color-status-pending-solid: light-dark(var(--color-pending-600), var(--color-pending-400));

  --color-status-inactive-fg:    light-dark(var(--color-inactive-600), var(--color-inactive-400));
  --color-status-inactive-bg:    light-dark(var(--color-inactive-50),  var(--color-inactive-900));
  --color-status-inactive-solid: light-dark(var(--color-inactive-600), var(--color-inactive-400));

  /* ---- Accent tones — NEW IN V2 ----
   *
   * THE ANSWER TO "THE PALETTE READS AS MONOCHROME GREEN". Three tones a component may carry when
   * it needs variety rather than status: the brand green, the brand teal and the brand amber. A KPI
   * card's icon chip is the first caller. They are NOT status tones - nothing here means "this
   * record is in trouble" - which is why they are named for the hue rather than for a state.
   *
   * Amber's foreground is -700 on light and never -500: §2 measures -500 at 3.0:1 on white, which
   * passes SC 1.4.11 for a shape and fails SC 1.4.3 for a word. */
  --color-tone-brand-fg: light-dark(var(--color-primary-600), var(--color-primary-300));
  --color-tone-brand-bg: light-dark(var(--color-primary-50),  var(--color-primary-900));
  --color-tone-teal-fg:  light-dark(var(--color-secondary-600), var(--color-secondary-300));
  --color-tone-teal-bg:  light-dark(var(--color-secondary-100), var(--color-secondary-900));
  --color-tone-amber-fg: light-dark(var(--color-accent-700), var(--color-accent-300));
  --color-tone-amber-bg: light-dark(var(--color-accent-100), var(--color-warning-900));

  /* ---- Elevation ink, resolved per theme ---- */
  --color-shadow-ambient: light-dark(var(--color-shadow-ambient-light), var(--color-shadow-ambient-dark));
  --color-shadow-key:     light-dark(var(--color-shadow-key-light),     var(--color-shadow-key-dark));

  /* ---- Fixed across themes ----
   *
   * Product photography keeps a light backdrop in every theme so packaging colours stay true and
   * white boxes remain visible. A pharma-catalogue requirement, not a style choice. */
  --color-product-image-background: #F6F8F7;
}

/* ---- Forcing a theme on a subtree ----
 *
 * color-scheme is what light-dark() reads, and it inherits - so these two attributes switch a whole
 * subtree, not just the element. That is what makes /design-system able to show the same component
 * in both themes on one screen, and it is the same hook a persisted per-user toggle will set on
 * <html> when that ships.
 *
 * The page's own default is `color-scheme: light dark` in base.css, which follows the operating
 * system. */
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"]  { color-scheme: dark; }

/* ---- Typography (design-system.md §5) ---- */
:root {
  --font-family-ui:      "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-family-display: "Manrope", var(--font-family-ui);

  --font-size-xs:   0.75rem;   /* 12px */
  --font-size-sm:   0.875rem;  /* 14px */
  --font-size-base: 1rem;      /* 16px */
  --font-size-lg:   1.125rem;  /* 18px */
  --font-size-xl:   1.25rem;   /* 20px */
  --font-size-2xl:  1.5rem;    /* 24px */
  --font-size-3xl:  1.875rem;  /* 30px */
  --font-size-4xl:  2.25rem;   /* 36px */

  --line-height-tight:   1.25;  /* headings, KPI figures */
  --line-height-normal:  1.5;   /* body, form fields */
  --line-height-relaxed: 1.6;   /* long-form help text */

  /* DISPLAY SIZES ONLY - never body text, and never below --font-size-xl. A face drawn for text
   * is spaced for text; at 24px and up that spacing reads loose, and pulling it in slightly is
   * what makes a heading look set rather than typed. §5. */
  --letter-spacing-tight: -0.01em;

  /* NEW IN V2 — THE OPPOSITE END, AND IT HAS EXACTLY ONE JOB. A small uppercase label - a KPI's
   * caption, a section eyebrow - is unreadable at its natural spacing: capitals are drawn to sit
   * beside lowercase, and a run of them at 12px closes up. Opening it slightly is what separates a
   * label that looks designed from one that looks shouted. Never on sentence-case text. */
  --letter-spacing-wide: 0.06em;

  --font-weight-regular:  400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;
  --font-weight-bold:     700;
}

/* ---- Space, shape, elevation, motion, layout (design-system.md §6) ---- */
:root {
  /* 4px grid */
  --space-0:  0;
  --space-1:  0.25rem;  --space-2:  0.5rem;   --space-3: 0.75rem;
  --space-4:  1rem;     --space-5:  1.25rem;  --space-6: 1.5rem;
  --space-8:  2rem;     --space-10: 2.5rem;   --space-12: 3rem;
  --space-16: 4rem;

  /* RADII OPENED UP IN V2. 4/8/12 is the shape of a utilitarian admin tool; a couple of pixels more
   * on each step is most of what separates "functional" from "considered" at a glance, and it costs
   * nothing. --radius-xs is new, for the smallest things that still should not be square: a
   * checkbox, a colour swatch, an icon chip's inner corner. */
  --radius-xs:   3px;
  --radius-sm:   6px;    /* badges on dense tables, checkboxes */
  --radius-md:   10px;   /* buttons, inputs, selects */
  --radius-lg:   14px;   /* cards, modals, panels */
  --radius-xl:   20px;   /* the largest containers — a dialog on a wide screen */
  --radius-full: 9999px; /* status pills, avatars */

  /* ---- Elevation ----
   *
   * A REAL LADDER IN V2, NOT THREE UNRELATED BLURS. Every step is TWO shadows: a tight ambient one
   * that grounds the object, and a wider key one offset downward that gives it height. One blur
   * alone reads as a smudge; the pair is what the eye accepts as depth.
   *
   * The ink comes from --color-shadow-* so the whole ladder re-inks per theme without any step
   * being redefined. On dark, elevation is carried mostly by the SURFACE steps - a shadow on
   * near-black has little to darken - which is why the dark inks are much heavier. */
  --shadow-xs: 0 1px 2px var(--color-shadow-ambient);
  --shadow-sm: 0 1px 2px var(--color-shadow-ambient),
               0 2px 6px -2px var(--color-shadow-key);
  --shadow-md: 0 2px 4px -1px var(--color-shadow-ambient),
               0 8px 18px -6px var(--color-shadow-key);
  --shadow-lg: 0 4px 8px -2px var(--color-shadow-ambient),
               0 20px 36px -10px var(--color-shadow-key);
  --shadow-xl: 0 8px 16px -4px var(--color-shadow-ambient),
               0 32px 60px -14px var(--color-shadow-key);

  /* ---- Motion ----
   *
   * §9 rule 5 suppresses all of it under prefers-reduced-motion, globally, so nothing below needs
   * to ask. --duration-slow and --easing-emphasized are new and exist for the dialog: an overlay
   * that arrives at button speed reads as a flicker rather than as a thing appearing. */
  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-slow: 280ms;
  --easing-standard: cubic-bezier(0.2, 0, 0.2, 1);
  --easing-emphasized: cubic-bezier(0.2, 0, 0, 1);

  --layout-sidebar-width: 260px;
  --layout-sidebar-width-collapsed: 72px;
  --layout-topbar-height: 64px;
  --layout-content-max-width: 1440px;
  --layout-touch-target-min: 44px;

  /* THE WIDEST A SINGLE READABLE COLUMN MAY GET - a column of form controls, a lede, a panel's
   * introduction - and §6 had no answer for any of them.
   *
   * 32rem = 512px, on the 4px grid. The widest single column that still reads as ONE column at
   * --font-size-base, and deliberately WIDER than the signed-out card's 400px: that card is the
   * only object on its page, while this one sits inside a padded panel, beside a sidebar, under a
   * page header.
   *
   * PENDING SIGN-OFF - design-system.md §11 item 18. */
  --layout-form-max-width: 32rem;

  /* THE WIDEST A READ-ONLY, TWO-COLUMN OVERLAY MAY GET. A SECOND VALUE RATHER THAN A WIDER FIRST
   * ONE, because the two answer different questions and only one of them is about reading.
   *
   * --layout-form-max-width is the measure of a single column somebody TYPES into: one caret, one
   * field at a time, and 512px is already the widest an input reads as one control at. Widening it
   * to fit a two-column detail would put a 56rem email field back on /admin/users, which is the
   * exact defect it was introduced to fix.
   *
   * A read-only detail is the opposite shape. Nothing is typed, the eye moves between panels rather
   * than along a line, and the constraint is how much a reader must SCROLL to see the product they
   * opened. At 32rem the product ficha is one long column - photograph, then identity, then eight
   * monograph rows - and a reader on a 1080p desktop scrolls a dialog inside a screen with room to
   * spare.
   *
   * 56rem = 896px, which is 40rem of content once the dialog's own padding is taken off, and 40rem
   * is not a new number: it is exactly the threshold `.sw-detail`'s container query already uses to
   * put its panels side by side. So this value is chosen to CROSS a line the stylesheet had already
   * drawn, and the two-column layout is the container query firing rather than any new rule.
   *
   * Below `md` it does not apply at all - the dialog is a full-screen sheet and this is inside the
   * md media query. design-system.md §6 and §8.12. */
  --layout-reading-max-width: 56rem;

  /* THE WIDEST A DIALOG WHOSE CONTENT IS A SELECTION GRID MAY GET. A THIRD VALUE, AND THE ARGUMENT
   * FOR IT IS THAT NEITHER OF THE OTHER TWO IS ABOUT THIS SHAPE.
   *
   * --layout-form-max-width is the measure of a single column somebody TYPES into: one caret, one
   * field at a time. --layout-reading-max-width is how far the eye travels between panels of prose
   * nobody edits. A form whose body is thirteen checkboxes is neither — nothing is typed, and
   * nothing is read at length. What decides its width is HOW MANY OPTIONS FIT ON A ROW.
   *
   * 44rem = 704px, on the 4px grid, and derived rather than chosen. `.sw-fieldset__options` is
   * `repeat(auto-fit, minmax(12rem, 1fr))` with a --space-4 gap, so three tracks need
   * 3 x 12rem + 2 x 1rem = 38rem of grid. The dialog's own padding at md is --space-6 a side, which
   * is 3rem, so 41rem is the floor and 44rem is that plus a rem of slack either side. At 32rem the
   * grid gets 29rem and can only ever make TWO columns - the auto-fit is real and the container
   * never gives it the room.
   *
   * WHAT THIS IS NOT: it is not "the export dialog looked cramped". Widening a form dialog in
   * general would put a 44rem e-mail field back on /admin/users, which is the defect
   * --layout-form-max-width exists to prevent. This applies only where the content is a grid of
   * equal short options, and it is opt-in for that reason.
   *
   * Below `md` it does not apply at all - the dialog is a full-screen sheet and this is inside the
   * md media query. design-system.md §8.12. */
  --layout-selection-max-width: 44rem;
}

/* ---- Iconography (design-system.md §7) ---- */
:root {
  --icon-size-sm: 16px;   /* inline with 12–14px text, dense table actions */
  --icon-size-md: 20px;   /* default: menus, buttons, table rows */
  --icon-size-lg: 24px;   /* primary entry points, KPI cards */
  --icon-stroke-width: 1.75;
}

/* ===== LAYER 3 — COMPONENT TOKENS whose value derives from a primitive =====
 *
 * design-system.md §1: a Layer 3 token normally lives beside the component that owns it. It lives
 * HERE when its value derives from a Layer 1 primitive, because "never referenced outside this
 * file" is absolute and where the token is written down is not.
 */
:root {
  /* The signed-out page background.
   *
   * THE SEMANTIC LAYER HAS NO ANSWER, and the reason is measurable: --color-surface-page against
   * the card's --color-surface-primary is about 1.03:1 on light. That is not a separation, it is
   * two whites. It matters on this page and nowhere else, because the login page has no chrome at
   * all - the card is the ONLY object on it.
   *
   * BOTH STOPS ARE THEMED, which is why light-dark() is inside the gradient rather than around it:
   * a gradient is not a colour and cannot be wrapped, but its stops are.
   *
   * PENDING SIGN-OFF - design-system.md §11 item 13. */
  --color-auth-page-background: linear-gradient(
    180deg,
    light-dark(var(--color-primary-50), var(--color-neutral-950)) 0%,
    light-dark(var(--color-surface-page), var(--color-neutral-975)) 60%
  );

  /* The skeleton placeholder, and the sheen that travels across it.
   *
   * THE SEMANTIC LAYER HAS NO ANSWER because a skeleton is not a surface, a border or a text
   * colour - it is a shape standing in for content that has not arrived. Two values rather than
   * one, because the shimmer is a gradient travelling across a base and a single colour cannot
   * express movement. The BASE is the darker of the two on light and the LIGHTER of the two on
   * dark: the placeholder has to read as an object against the card it sits on, and that flips.
   *
   * PENDING SIGN-OFF - design-system.md §11 item 10. */
  --color-skeleton-base:  light-dark(var(--color-neutral-200), var(--color-neutral-825));
  --color-skeleton-sheen: light-dark(var(--color-neutral-50),  var(--color-neutral-775));
}
