/*!
 * ZIC Theme — Layer 1 · Token contract, motion & compatibility aliases
 * ============================================================================
 *
 * Load order (see src/templates/layouts/partials/styles.html):
 *
 *   1. variables.css          <- this file  (structure, motion, alias shims)
 *   2. variables-light.css    <- `:root` light palette (the default)
 *   3. variables-dark.css     <- `[data-bs-theme="dark"], html.dark-style`
 *   4. materio-overrides.css  <- maps Materio `--bs-*` onto the ZIC tokens
 *   5. zic-theme.css          <- component polish built on the tokens
 *
 * Theme state is expressed twice on <html> so that both worlds agree:
 *   * `data-bs-theme="light|dark"` — Materio/Bootstrap's native mechanism.
 *   * `.light-style` / `.dark-style` — the ZIC class contract.
 * The switcher always writes both; either one alone is enough to theme.
 *
 * ---------------------------------------------------------------------------
 * TOKEN INVENTORY — every `--zic-*` name defined by this architecture.
 * Values live in variables-light.css / variables-dark.css unless noted.
 * ---------------------------------------------------------------------------
 *
 * Surfaces
 *   --zic-surface-primary        Raised content surface (cards, panels, navbar, sidebar)
 *   --zic-surface-secondary      App canvas behind the raised surface
 *   --zic-surface-elevated       Floating surface (dropdown, modal, popover, toast)
 *   --zic-surface-tertiary       Recessed surface (table heads, wells, hover rows)
 *   --zic-surface-overlay        Modal backdrop (translucent)
 *   --zic-surface-*-rgb          Comma triplets for the four opaque surfaces
 *
 * Text
 *   --zic-text-primary / -secondary / -disabled / -inverse
 *   --zic-text-primary-rgb / --zic-text-secondary-rgb
 *
 * Borders
 *   --zic-border-default / --zic-border-strong / --zic-border-focus
 *
 * Brand & interactive blues
 *   --zic-primary                Accent blue for icons, borders, decoration
 *   --zic-primary-text           AA-safe blue for text and links
 *   --zic-primary-hover / -active
 *   --zic-primary-fill           AA-safe solid background (white on it passes)
 *   --zic-primary-contrast       Foreground for --zic-primary-fill
 *   --zic-accent                 Bright highlight blue (never used for body text)
 *   --zic-primary-rgb
 *
 * Status (semantic, never raw)
 *   --zic-status-{success,warning,danger,info,neutral}
 *   --zic-status-*-text          AA-safe foreground on any ZIC surface
 *   --zic-status-*-fill          AA-safe solid background
 *   --zic-status-*-contrast      Foreground for the matching -fill
 *   --zic-status-*-bg-subtle     Tinted badge/banner background
 *   --zic-status-*-border-subtle Tinted badge/banner border
 *   --zic-status-*-rgb           Comma triplets for translucent effects
 *
 * Interactive states
 *   --zic-interactive-hover / -active / -focus-ring
 *
 * Shadows
 *   --zic-shadow-sm / -md / -lg / -xl
 *
 * Motion (defined below — identical in every theme)
 *   --zic-transition-fast (150ms) / -normal (250ms) / -slow (400ms)
 *   --zic-transition-ease
 *   --zic-theme-reveal-duration / -ease          The one theme-switch animation
 *
 * Structure (defined below)
 *   --zic-space-1 … -8                            8px baseline scale
 *   --zic-grid-gap / -section-gap / -item-gap     named rhythm
 *   --zic-page-pad-x / -y, --zic-card-pad-*       named rhythm
 *   --zic-container-max                           1600px content ceiling
 *   --zic-radius-xs / -sm / -md / -lg / -xl / -pill
 *   --zic-focus-ring-width / -offset
 *   --zic-z-sticky / -sidebar / -navbar / -overlay / -modal / -toast
 *
 * Component geometry (defined below)
 *   --zic-nav-*                                   rail width, item, submenu, logo
 *   --zic-card-*                                  radius, padding, grid, accent
 *
 * Contrast budget: every `-text` token is >= 4.5:1 on every ZIC surface, and
 * every `-fill` is >= 4.5:1 against its `-contrast`. Verified in
 * docs/UI_THEME_GUIDE.md.
 */

:root {
  /* -------------------------------------------------------------------------
   * Motion. Identical in both themes so a theme switch never changes timing.
   * Shorthands include the easing, so `transition: color var(--zic-transition-fast)`
   * reads as a complete transition value.
   * ---------------------------------------------------------------------- */
  --zic-transition-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --zic-transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
  --zic-transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1);
  --zic-transition-slow: 400ms cubic-bezier(0.4, 0, 0.2, 1);
  /* Decelerating curve for things that arrive — a dialog settling, a sheet
     sliding up. `ease` front-loads the movement and stops dead. */
  --zic-transition-ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* Overlay motion, read by the ZIC widget surfaces. The modal chrome — its
     entrance and its scrim — is the shell's own since the Materio restoration,
     so it is no longer timed from here. */
  --zic-modal-duration: 250ms;

  /* Timing for the unified theme switch. ONE duration for the whole surface,
     because the switch is one animation rather than N per-element fades. The
     per-element tokens that used to live here are gone: they existed only for
     the blanket cross-fade, and a token that no longer does anything is a trap
     for the next person. */
  --zic-theme-reveal-duration: 380ms;
  --zic-theme-reveal-ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* -------------------------------------------------------------------------
   * Focus ring geometry (colour is themed via --zic-interactive-focus-ring).
   * ---------------------------------------------------------------------- */
  --zic-focus-ring-width: 3px;
  --zic-focus-ring-offset: 2px;

  /* -------------------------------------------------------------------------
   * Radii.
   * ---------------------------------------------------------------------- */
  --zic-radius-xs: 0.25rem;
  --zic-radius-sm: 0.375rem;
  --zic-radius-md: 0.625rem;
  --zic-radius-lg: 0.875rem;
  --zic-radius-xl: 1.25rem;
  --zic-radius-pill: 999px;

  /* -------------------------------------------------------------------------
   * Spacing — an 8px baseline grid.
   *
   * The numeric steps are the raw scale; the named tokens below are the only
   * ones layout code should use, so that "24px between cards" is expressed
   * once rather than re-derived at every call site. A 4px half-step (`-1`)
   * exists for optical adjustments inside a component (icon/label gaps) and is
   * deliberately absent from the named layer.
   * ---------------------------------------------------------------------- */
  --zic-space-1: 4px;
  --zic-space-2: 8px;
  --zic-space-3: 16px;
  --zic-space-4: 24px;
  --zic-space-5: 32px;
  --zic-space-6: 40px;
  --zic-space-7: 48px;
  --zic-space-8: 64px;

  /* Named rhythm. */
  --zic-grid-gap: var(--zic-space-4); /* between cards in a grid */
  --zic-section-gap: var(--zic-space-5); /* between major sections */
  --zic-item-gap: var(--zic-space-3); /* between related items */
  --zic-page-pad-x: var(--zic-space-5);
  --zic-page-pad-y: var(--zic-space-4);
  --zic-card-pad-compact: var(--zic-space-4);
  --zic-card-pad-spacious: var(--zic-space-5);
  --zic-container-max: 1600px;

  /* -------------------------------------------------------------------------
   * Form control geometry.
   *
   * Named so that an input, a select and a button dropped into the same
   * `.input-group` can be told to agree, rather than each carrying its own
   * magic numbers. Colours are NOT here — every form colour is a theme token.
   * ---------------------------------------------------------------------- */
  --zic-control-height-sm: 32px;
  --zic-control-height: 40px;
  --zic-control-height-lg: 48px;
  --zic-control-padding-x-sm: 8px;
  --zic-control-padding-x: 12px;
  --zic-control-radius: 8px;
  --zic-control-check-size: 20px;

  /* Opacity applied to a disabled control. Themed: see the palettes. */
  --zic-control-disabled-opacity: 0.5;

  /* -------------------------------------------------------------------------
   * Typography.
   *
   * Two notes on the brief's numbers.
   *
   * The scale is described as modular 1.25, but the listed steps are not:
   * 1.25^0 is 16 and the chain would run 16 / 20 / 25 / 31 / 39. The eight
   * values below are a hybrid (a 12/14/16 trio then 18/20/24/30/36); they are
   * implemented as listed, because they are what the design actually asks for.
   *
   * These are an *available* scale, not a replacement for the shell's body
   * size. `--bs-body-font-size` stays 0.9375rem (15px) — see the guide, section
   * 15: applying `-base` to the document would relayout every page in the app,
   * which is a separate decision from defining the scale.
   *
   * Line heights are the brief's pixel pairs rather than unitless ratios: each
   * step is a complete, deliberate size/leading pairing.
   * ---------------------------------------------------------------------- */
  --zic-font-family-sans:
    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu,
    Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
  /* JetBrains Mono and Fira Code are not shipped as webfonts by this project;
     they head the stack so a machine that has them installed uses them, and
     everything else falls through the shell's own faces. */
  --zic-font-family-mono:
    'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Menlo, Monaco, Consolas,
    'Liberation Mono', 'Courier New', monospace;

  --zic-font-size-xs: 12px;
  --zic-font-size-sm: 14px;
  --zic-font-size-base: 16px;
  --zic-font-size-lg: 18px;
  --zic-font-size-xl: 20px;
  --zic-font-size-2xl: 24px;
  --zic-font-size-3xl: 30px;
  --zic-font-size-4xl: 36px;

  --zic-line-height-xs: 16px;
  --zic-line-height-sm: 20px;
  --zic-line-height-base: 24px;
  --zic-line-height-lg: 28px;
  --zic-line-height-xl: 28px;
  --zic-line-height-2xl: 32px;
  --zic-line-height-3xl: 36px;
  --zic-line-height-4xl: 40px;

  --zic-font-weight-light: 300;
  --zic-font-weight-regular: 400;
  --zic-font-weight-medium: 500;
  --zic-font-weight-semibold: 600;
  --zic-font-weight-bold: 700;

  /* Optically tightened tracking for display sizes. Large text set at the same
     tracking as body copy reads loose. */
  --zic-font-tracking-tight: -0.02em;
  --zic-font-tracking-normal: 0;
  --zic-font-tracking-wide: 0.02em;

  /* -------------------------------------------------------------------------
   * Navigation geometry.
   *
   * Only the two sizes the shell reads are declared: the rail's expanded and
   * collapsed widths, mapped onto `--bs-menu-width` /
   * `--bs-menu-collapsed-width` by `nav.css`. Item height, radius, margins and
   * the submenu indent are Materio's own and are no longer restated.
   * ---------------------------------------------------------------------- */
  --zic-nav-width: 260px;
  --zic-nav-width-collapsed: 80px;
  --zic-nav-logo: 40px;

  /* -------------------------------------------------------------------------
   * Card geometry.
   *
   * `.card` is the app's panel primitive (226 uses), so these drive Bootstrap's
   * `--bs-card-*` variables rather than restating sizes at the call site. The
   * two Y paddings differ on purpose: a header reads better slightly tighter
   * than a body, and a footer tighter still.
   * ---------------------------------------------------------------------- */
  --zic-card-radius: 12px;
  --zic-card-gap: var(--zic-space-4); /* 24px between grid cards */
  --zic-card-list-gap: var(--zic-space-3); /* 16px between stacked cards */
  --zic-card-grid-min: 300px;
  --zic-card-accent-width: 4px;

  /* -------------------------------------------------------------------------
   * Stacking scale. Keeps ZIC chrome above Materio's own layers without
   * reaching for arbitrary numbers at the call site.
   * ---------------------------------------------------------------------- */
  --zic-z-sticky: 1020;
  --zic-z-sidebar: 1030;
  --zic-z-navbar: 1040;
  --zic-z-overlay: 1050;
  --zic-z-modal: 1060;
  --zic-z-toast: 1090;
}

/* ---------------------------------------------------------------------------
 * Unified theme transition.
 *
 * There is NO global colour transition. The old approach — one
 * `*, *::before, *::after { transition: background-color … }` rule — is what
 * produced the staggered "skeleton" flash this file used to cause: every
 * element started its own fade from the moment the class changed, so the
 * sidebar, navbar, cards and tables each settled on a different frame. Per-
 * element transitions cannot be made simultaneous from CSS, because they are
 * per-element.
 *
 * The switch is now ONE surface: `document.startViewTransition` snapshots the
 * whole viewport once, the theme class is written inside the update callback,
 * and a second snapshot is revealed over the first with a circular clip-path.
 * Nothing per-element is captured mid-transition, so nothing can desync.
 *
 * The atomicity guard `zt-instant` is applied on BOTH paths — including the
 * View Transitions one — because a per-element transition that happens to be
 * running when the new snapshot is taken would be captured at its *old* value.
 * That is the mechanism behind "charts flash old colours then snap".
 * ------------------------------------------------------------------------- */

/* Atomic guard. Applied for the duration of a theme write; removed on the next
   frame. `!important` because it has to outrank every component transition. */
html.zt-instant,
html.zt-instant *,
html.zt-instant *::before,
html.zt-instant *::after {
  transition: none !important;
  animation: none !important;
}

/* --- View Transitions path ------------------------------------------------
 *
 * The default cross-fade is replaced: the OLD snapshot is static, the NEW one
 * is revealed through a circle that grows from the toggle button, so the two
 * themes are never both partly visible. `--zt-x`/`--zt-y` are the button's
 * centre, written by the switcher.
 * ------------------------------------------------------------------------ */
html.theme-anim::view-transition-old(root) {
  animation: none;
  /* Hold the outgoing theme underneath rather than fading it out: the reveal
     is a mask, not a cross-fade. */
  opacity: 1;
}

html.theme-anim::view-transition-new(root) {
  animation: zt-reveal var(--zic-theme-reveal-duration) var(--zic-theme-reveal-ease);
  clip-path: circle(0px at var(--zt-x, 50%) var(--zt-y, 50%));
}

@keyframes zt-reveal {
  to {
    clip-path: circle(150vmax at var(--zt-x, 50%) var(--zt-y, 50%));
  }
}

/* The overlay layer must not swallow the reveal. */
html.theme-anim::view-transition-image-pair(root) {
  isolation: auto;
}

/* --- Fallback path -------------------------------------------------------
 *
 * `#zt-flash` is a full-viewport veil at zero opacity. Without View
 * Transitions the theme is written atomically (see `zt-instant` above), and the
 * veil is lifted for two frames purely as a perceptual bridge — it masks the
 * one-frame changeover so the switch reads as a transition rather than a jump.
 *
 * `pointer-events: none` always: a decorative veil must never intercept a
 * click, and it must never be a hit target during the 100ms it is visible.
 * ------------------------------------------------------------------------ */
#zt-flash {
  position: fixed;
  inset: 0;
  z-index: 2147483600;
  pointer-events: none;
  opacity: 0;
  background-color: var(--zic-surface-secondary);
} 

#zt-flash.zt-flash-on {
  opacity: 0.6;
}

/* Users who asked for less motion get an instant switch with no reveal and no
   veil. The switcher also checks the media query in JS; this is the CSS half of
   the same contract, so a stray class cannot animate the page. */
@media (prefers-reduced-motion: reduce) {
  html.theme-anim::view-transition-new(root) {
    animation: none;
    clip-path: none;
  }

  #zt-flash {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
 * Paint the canvas from the token layer before <body> exists.
 *
 * The head script applies the theme before first paint, so this is never the
 * "flash" — it is the safety net for overscroll and for the one frame between
 * the stylesheet landing and the body background being resolved. Without it a
 * dark session can leak a white strip at the top and bottom of the viewport.
 * ------------------------------------------------------------------------- */
html {
  background-color: var(--zic-surface-secondary, #fafafa);
}

/* ---------------------------------------------------------------------------
 * Compatibility aliases.
 *
 * The first theme pass shipped business-state names (`--zic-status-active`,
 * `-pending`, `-overdue`, `-completed`). They are now expressed in terms of the
 * semantic status tokens so existing templates keep working while new work
 * targets `--zic-status-success` and friends.
 * ------------------------------------------------------------------------- */
:root {
  --zic-status-active: var(--zic-status-success);
  --zic-status-active-rgb: var(--zic-status-success-rgb);
  --zic-status-pending: var(--zic-status-warning);
  --zic-status-pending-rgb: var(--zic-status-warning-rgb);
  --zic-status-overdue: var(--zic-status-danger);
  --zic-status-overdue-rgb: var(--zic-status-danger-rgb);
  --zic-status-completed: var(--zic-status-info);
  --zic-status-completed-rgb: var(--zic-status-info-rgb);
}
