/* backend/src/main/resources/static/infrastructure/gabion-contract.css */

/* ==============================================
   GABION CSS CONTRACT v1.0

   Required set of CSS custom properties.
   Every starter MUST override required variables
   in .page-light and .page-dark.

   Modules use ONLY var(--gb-*).
   No hardcoded colors. No .page-dark duplication.

   Derived colors are formulas of the color they derive from (borders
   and shadows from the body text, translucent fills from the color
   they tint, hover states darker than the color they hover), the same
   canonical form a starter's theme uses: a fallback base carries its
   derived colors along.

   Loading order:
   1. gabion-contract.css  (this file — fallback values)
   2. gabion-reset.css     (minimal reset)
   3. starter theme.css    (overrides for .page-light / .page-dark)
   4. starter globals      (base, fonts, layout, animations)
   5. starter components   (header, footer, button, section…)
   6. module styles        (global + page-specific)
   ============================================== */

:root {
  /* === COLORS — Background (stone palette — warm off-white) === */
  --gb-bg-primary: #fafaf9;
  --gb-bg-surface: #f5f5f4;
  --gb-bg-elevated: #ffffff;
  --gb-bg-inset: #e7e5e4;

  /* === COLORS — Text (warm grays, WCAG AA compliant) === */
  --gb-text-primary: #1c1917;
  --gb-text-secondary: #57534e;
  --gb-text-tertiary: #746e68;
  --gb-text-heading: #0c0a09;
  --gb-text-on-accent: #ffffff;

  /* === COLORS — Border (the body text at low opacity) === */
  --gb-border-default: color-mix(in srgb, var(--gb-text-primary) 10%, transparent);
  --gb-border-subtle: color-mix(in srgb, var(--gb-text-primary) 6%, transparent);
  --gb-border-strong: color-mix(in srgb, var(--gb-text-primary) 18%, transparent);

  /* === COLORS — Accent === */
  --gb-accent-primary: #2563eb;
  --gb-accent-hover: color-mix(in srgb, var(--gb-accent-primary), black 18%);
  --gb-accent-subtle: color-mix(in srgb, var(--gb-accent-primary) 6%, transparent);

  /* Accent surface: action background carrying --gb-text-on-accent.
     A separate axis from the accent itself — the link color is tuned
     against the page background, the action surface against the white
     label it carries. */
  --gb-accent-surface: #2563eb;
  --gb-accent-surface-hover: color-mix(in srgb, var(--gb-accent-surface), black 18%);

  /* === COLORS — Semantic ===
     Four roles per meaning, each a different job:
     signal (draws the eye: icons, borders, fills),
     -text (readable as words, ≥4.5:1 on page backgrounds and tinted
     badge fills), -subtle (translucent fill for badges/callouts),
     -surface (fill carrying --gb-text-on-accent). One value is never
     best at two of these jobs. */
  --gb-color-success: #16a34a;
  --gb-color-success-text: #166534;
  --gb-color-success-subtle: color-mix(in srgb, var(--gb-color-success) 8%, transparent);
  --gb-color-success-surface: #15803d;
  --gb-color-warning: #d97706;
  --gb-color-warning-text: #92400e;
  --gb-color-warning-subtle: color-mix(in srgb, var(--gb-color-warning) 8%, transparent);
  --gb-color-error: #dc2626;
  --gb-color-error-text: #b91c1c;
  --gb-color-error-subtle: color-mix(in srgb, var(--gb-color-error) 8%, transparent);
  --gb-color-error-surface: #b91c1c;
  --gb-color-error-surface-hover: color-mix(in srgb, var(--gb-color-error-surface), black 17%);
  --gb-color-info: #2563eb;
  --gb-color-info-text: #1d4ed8;
  --gb-color-info-subtle: color-mix(in srgb, var(--gb-color-info) 8%, transparent);
  --gb-color-purple: #8e24aa;
  --gb-color-purple-text: #7b1fa2;
  --gb-color-purple-subtle: color-mix(in srgb, var(--gb-color-purple) 8%, transparent);

  /* === COLORS — Backdrop overlays === */
  --gb-backdrop: rgba(0, 0, 0, 0.5);
  --gb-backdrop-light: rgba(0, 0, 0, 0.4);
  --gb-backdrop-heavy: rgba(0, 0, 0, 0.7);

  /* === TYPOGRAPHY — families === */
  --gb-font-primary: -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  --gb-font-mono: "SF Mono", "Fira Code", "Fira Mono",
    "Roboto Mono", Menlo, monospace;

  /* Heading face and the weight headings are set at. A pair, because
     the weight that makes a heading is a property of the face: a sans
     needs bold to read as a heading, a display serif is one at regular
     weight — and a face asked for a weight it has no file for is
     synthesised into a smear. The fallback is the text face in bold,
     which is also what a starter with a single family declares. */
  --gb-font-heading: var(--gb-font-primary);
  --gb-font-heading-weight: 700;

  --gb-font-weight-normal: 400;
  --gb-font-weight-medium: 500;
  --gb-font-weight-semibold: 600;
  --gb-font-weight-bold: 700;

  /* === TYPOGRAPHY — type roles ===
     A role is a triple (size, leading, tracking) chosen by the job of
     the text, not by its size: leading is a function of size (display
     sizes sit tight, running text needs air), and tracking flips sign
     with size (large type is tightened, small uppercase is opened). The
     three axes are separate properties so a component may take a role's
     size and keep its own leading (a button's line box is geometry).
     Heading sizes ramp between narrow and wide viewports; every other
     role is fixed. */
  --gb-type-heading-1-size: clamp(1.875rem, 1.49rem + 1.58vw, 2.5rem);
  --gb-type-heading-1-leading: 1.12;
  --gb-type-heading-1-tracking: -0.015em;

  --gb-type-heading-2-size: clamp(1.5rem, 1.35rem + 0.63vw, 1.75rem);
  --gb-type-heading-2-leading: 1.2;
  --gb-type-heading-2-tracking: -0.01em;

  --gb-type-heading-3-size: clamp(1.25rem, 1.17rem + 0.32vw, 1.375rem);
  --gb-type-heading-3-leading: 1.3;
  --gb-type-heading-3-tracking: -0.005em;

  --gb-type-lead-size: 1.1875rem;
  --gb-type-lead-leading: 1.35;
  --gb-type-lead-tracking: 0;

  --gb-type-body-size: 1.0625rem;
  --gb-type-body-leading: 1.65;
  --gb-type-body-tracking: 0;

  --gb-type-secondary-size: 0.9375rem;
  --gb-type-secondary-leading: 1.55;
  --gb-type-secondary-tracking: 0;

  --gb-type-caption-size: 0.8125rem;
  --gb-type-caption-leading: 1.45;
  --gb-type-caption-tracking: 0.01em;

  /* Overline: short uppercase label; the tracking assumes
     text-transform: uppercase on the consumer. */
  --gb-type-overline-size: 0.875rem;
  --gb-type-overline-leading: 1.4;
  --gb-type-overline-tracking: 0.045em;

  /* === SPACING === */
  --gb-spacing-xs: 0.25rem;
  --gb-spacing-sm: 0.5rem;
  --gb-spacing-md: 1rem;
  --gb-spacing-lg: 1.5rem;
  --gb-spacing-xl: 2rem;
  --gb-spacing-2xl: 3rem;
  --gb-spacing-3xl: 4rem;

  /* === BORDER RADIUS === */
  --gb-radius-sm: 4px;
  --gb-radius-md: 8px;
  --gb-radius-lg: 12px;
  --gb-radius-xl: 16px;
  --gb-radius-full: 9999px;

  /* === SHADOWS (tinted with the body text) === */
  --gb-shadow-sm: 0 1px 2px color-mix(in srgb, var(--gb-text-primary) 6%, transparent);
  --gb-shadow-md: 0 2px 8px color-mix(in srgb, var(--gb-text-primary) 9%, transparent);
  --gb-shadow-lg: 0 8px 24px color-mix(in srgb, var(--gb-text-primary) 14%, transparent);
  --gb-shadow-none: none;

  /* === TRANSITIONS === */
  --gb-transition-fast: 150ms ease;
  --gb-transition-normal: 250ms ease;
  --gb-transition-slow: 350ms ease;

  /* === LAYOUT === */
  --gb-content-max-width: 1200px;
  --gb-content-narrow: 800px;
  --gb-content-wide: 1440px;
  --gb-content-ultrawide: 1920px;

  /* Measure: the comfortable line length of running text, a property
     of the type (≈66–75 characters at the body size), not of the
     layout. The --gb-content-* widths size columns and cards; a text
     column at 800px runs ~88 characters and the eye loses the start of
     the next line. In rem so it scales with the type, not with the
     font's glyph width. */
  --gb-measure: 46rem;

  /* Section gap: the rhythm between page sections. A different kind of
     distance from the spacing scale (component padding and gaps), not
     its next step — a larger step would leak into component spacing.
     Ramps with the viewport (80→160px), so sections need no media
     query for their vertical rhythm. */
  --gb-section-gap: clamp(5rem, 3rem + 5vw, 10rem);
  --gb-header-height: 64px;

  /* Browser frame: the color a mobile browser paints its own toolbar
     with, so the page and the frame around it read as one surface. The
     color of whatever sits at the top edge of the page — the page
     background here; a starter with a fixed header names the header's
     surface instead. A reference, not a value: it follows the theme
     through the token it points at. */
  --gb-browser-frame: var(--gb-bg-primary);

  /* === Z-INDEX SCALE === */
  --gb-z-dropdown: 100;
  --gb-z-sticky: 200;
  --gb-z-header: 300;
  --gb-z-overlay: 400;
  --gb-z-modal: 500;
}

/* Utility: hide elements via JS class toggle instead of inline style mutation */
.module-hidden {
  display: none !important;
}

/* Utility: page scroll lock while a modal surface (dialog, slide-in
   panel) is open. Toggled via body.classList, never via an inline
   style — a script that fails mid-way must not leave the page
   unscrollable. The lock is applied to the root element explicitly:
   the body's overflow propagates to the viewport only while the root
   declares none of its own, and any starter that styles html overflow
   would silently break a body-only lock. */
body.modal-open {
  overflow: hidden;
}

html:has(body.modal-open) {
  overflow: hidden;
}

/* The browser frame color, resolved. A browser reads the frame color
   from a meta element and accepts only a finished color there, never a
   custom property. This rule makes the engine do the resolving: the
   element takes the token as its own text color, and the page script
   copies the computed result into the element's content. Nothing is
   painted — a meta element has no box. */
meta[name="theme-color"] {
  color: var(--gb-browser-frame);
}

/* Utility: visually hidden, present in the accessibility tree.
   For labels that sighted users infer from layout (an avatar column
   header, an icon-only control). display:none / visibility:hidden do
   not fit — they remove the text from the accessibility tree too. */
.gb-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Utility: inline SVG icon wrapper for Thymeleaf SVG fragments */
.gb-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  vertical-align: middle;
}

.gb-icon svg {
  width: 100%;
  height: 100%;
}