/* ==========================================================================
   neobrutalism-theme / tokens
   --------------------------------------------------------------------------
   This file is the single source of truth. Every literal value in the theme
   lives here exactly once. The Tailwind adapters next to it (theme.css for
   v4, preset.js for v3) hold no values of their own; they point at these
   custom properties with var().

   Each group is annotated with the creative-direction axis the choice serves.
   The four axes are tone register, aesthetic philosophy, audience
   relationship, and sensory ambition. Read them at
   https://rampstack.co/framework/creative-direction

   Contrast ratios in the comments are measured against the ground
   (--nb-ground) or the fill named, and are WCAG 2.1 relative-luminance
   figures. Every text pairing here clears AA.
   ========================================================================== */

:root {
  /* ----------------------------------------------------------------------
     GROUND AND INK
     Aesthetic philosophy axis. A warm off-white rather than a pure white is
     what separates this register from flat minimalism: the ground reads as
     paper, so the hard-bordered surfaces sitting on it read as objects placed
     on paper. Ink is warm near-black, never #000, because a true black next
     to cream reads as a printing error rather than a decision.
     ---------------------------------------------------------------------- */
  --nb-ground: #fbf5ea;         /* page background, the warm paper */
  --nb-surface: #ffffff;        /* cards and raised panels sit above the ground */
  --nb-surface-muted: #f2e9d9;  /* recessed panels, table stripes, code blocks */
  --nb-ink: #141210;            /* text, borders, and shadows. 17.22:1 on ground */
  --nb-ink-muted: #57503f;      /* secondary text. 7.37:1 on ground, 6.64:1 on surface-muted */

  /* ----------------------------------------------------------------------
     ACTION COLORS
     Tone register axis. Saturated flat fills, no gradients and no tints,
     because a gradient would soften the edge this register is built on. The
     fills are loud enough to be read as intent from across the room, which is
     the Playful end of the tone axis behaving itself.
     ---------------------------------------------------------------------- */
  --nb-primary: #3d3bf0;            /* the one action color. White text: 6.81:1 */
  --nb-primary-ink: #ffffff;
  --nb-destructive: #c81e2b;        /* White text: 5.71:1 */
  --nb-destructive-ink: #ffffff;

  /* ----------------------------------------------------------------------
     THE ACCENT
     Sensory ambition axis. Exactly one color carries the dimensional play:
     the offset shadow under a featured surface is tinted with the accent
     while every other shadow stays ink. One tinted shadow per screen reads as
     craft. Three read as decoration, which is the Considered position tipping
     into something it is not.
     ---------------------------------------------------------------------- */
  --nb-accent: #f0620f;             /* Ink text: 5.75:1. Against ground: 3.00:1 */
  --nb-accent-ink: #141210;

  /* ----------------------------------------------------------------------
     FLAT SEMANTIC FILLS
     Aesthetic philosophy axis. Badges take ink text on a pale saturated fill
     rather than colored text on a tint. The hard border carries the boundary
     at 17.22:1, so the fill is free to be chosen for meaning instead of for
     legibility. That is the whole trade this register makes.
     ---------------------------------------------------------------------- */
  --nb-fill-success: #c6f24e;   /* ink on fill: 14.43:1 */
  --nb-fill-info: #7fd4f5;      /* ink on fill: 11.25:1 */
  --nb-fill-warning: #ffd84d;   /* ink on fill: 13.51:1 */
  --nb-fill-danger: #ff9eb5;    /* ink on fill:  9.62:1 */

  /* ----------------------------------------------------------------------
     BORDER
     Aesthetic philosophy axis. Two pixels is the working weight and three is
     reserved for the element that owns the screen. A one-pixel border belongs
     to a different register entirely; below two pixels the borders stop
     reading as structure and start reading as hairlines.
     ---------------------------------------------------------------------- */
  --nb-border-width: 2px;
  --nb-border-width-heavy: 3px;
  --nb-border-color: var(--nb-ink);

  /* ----------------------------------------------------------------------
     SHADOW
     Aesthetic philosophy axis, density made honest. Zero blur, full opacity,
     hard offset. A blurred shadow simulates a light source and asks the
     viewer to believe in a room; a hard offset states that one plane sits
     above another and declines to pretend otherwise.
     ---------------------------------------------------------------------- */
  --nb-shadow-offset-sm: 2px;
  --nb-shadow-offset: 4px;
  --nb-shadow-offset-lg: 6px;

  --nb-shadow-sm: var(--nb-shadow-offset-sm) var(--nb-shadow-offset-sm) 0 0 var(--nb-ink);
  --nb-shadow: var(--nb-shadow-offset) var(--nb-shadow-offset) 0 0 var(--nb-ink);
  --nb-shadow-lg: var(--nb-shadow-offset-lg) var(--nb-shadow-offset-lg) 0 0 var(--nb-ink);
  --nb-shadow-accent: var(--nb-shadow-offset-lg) var(--nb-shadow-offset-lg) 0 0 var(--nb-accent);

  /* ----------------------------------------------------------------------
     RADIUS
     Audience relationship axis. Restrained radii are the difference between
     addressing the reader as a peer and addressing them as a child. Square
     corners would put the brand above the reader; pill corners would put it
     below. Eight pixels is level ground.
     ---------------------------------------------------------------------- */
  --nb-radius-tight: 4px;   /* badges, tags, inline chips */
  --nb-radius: 8px;         /* buttons, inputs, cards */
  --nb-radius-pill: 999px;  /* avatars and pill toggles only */

  /* ----------------------------------------------------------------------
     TYPE
     Tone register axis. The stack is system fonts, so the theme loads no
     webfont and makes no network request. Weight does the work instead of
     typeface personality: 800 on headings against 400 on body is a wider
     jump than most systems take, and the jump is what carries the voice.
     ---------------------------------------------------------------------- */
  --nb-font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --nb-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --nb-weight-body: 400;
  --nb-weight-medium: 500;
  --nb-weight-bold: 700;
  --nb-weight-display: 800;

  --nb-text-display: 3.25rem;  /* 52px */
  --nb-text-h1: 2.5rem;        /* 40px */
  --nb-text-h2: 1.875rem;      /* 30px */
  --nb-text-h3: 1.375rem;      /* 22px */
  --nb-text-lead: 1.1875rem;   /* 19px */
  --nb-text-body: 1rem;        /* 16px, the floor for form inputs on iOS */
  --nb-text-sm: 0.875rem;      /* 14px, the floor for any body content */
  --nb-text-xs: 0.75rem;       /* 12px, labels and badges only, never prose */

  --nb-leading-tight: 1.05;
  --nb-leading-snug: 1.25;
  --nb-leading-body: 1.6;

  --nb-tracking-tight: -0.02em;
  --nb-tracking-wide: 0.06em;

  /* ----------------------------------------------------------------------
     SPACE
     Aesthetic philosophy axis. Controlled Maximalist earns its density by
     composing it, so the scale is fixed and arbitrary values are the thing
     that breaks the composition. Section rhythm holds at 64px on desktop and
     48px on mobile, which is the floor below which sections bleed together.
     ---------------------------------------------------------------------- */
  --nb-space-1: 4px;
  --nb-space-2: 8px;
  --nb-space-3: 12px;
  --nb-space-4: 16px;
  --nb-space-6: 24px;
  --nb-space-8: 32px;
  --nb-space-12: 48px;
  --nb-space-16: 64px;
  --nb-space-24: 96px;

  --nb-measure: 68ch;      /* prose measure */
  --nb-container: 1120px;  /* page max width */

  /* ----------------------------------------------------------------------
     MOTION
     Sensory ambition axis. The press moves the element into its own shadow by
     exactly the shadow offset, so the surface lands flush against the ground
     and the shadow disappears. It is the only motion the theme ships, and it
     is the one the reader feels rather than watches.
     ---------------------------------------------------------------------- */
  --nb-press-travel: var(--nb-shadow-offset);
  --nb-duration: 110ms;
  --nb-ease: cubic-bezier(0.2, 0, 0.2, 1);

  /* ----------------------------------------------------------------------
     FOCUS
     Audience relationship axis. The focus ring is offset outside the border
     so it never competes with it, and it uses the primary rather than the ink
     so a keyboard user can tell focus from structure at a glance.
     ---------------------------------------------------------------------- */
  --nb-ring: var(--nb-primary);  /* 6.28:1 against ground, clears the 3:1 UI floor */
  --nb-ring-width: 3px;
  --nb-ring-offset: 2px;

  /* ----------------------------------------------------------------------
     PLAY: ROTATION
     Tone register axis. Nothing on a grid is ever accidentally crooked, so a
     tilted element reads as placed by hand. The range stops at two degrees in
     each direction: past that the eye stops reading it as a placement and
     starts reading it as a mistake, and the Playful position turns into a
     broken layout. Four steps rather than one, so repeated tilts on a page do
     not land at the same angle and give the trick away.
     ---------------------------------------------------------------------- */
  --nb-tilt-1: -2deg;
  --nb-tilt-2: -1deg;
  --nb-tilt-3: 1.25deg;
  --nb-tilt-4: 2deg;

  /* ----------------------------------------------------------------------
     PLAY: STICKERS AND MOTIFS
     Sensory ambition axis. A sticker that sits inside its container is a
     badge; one that hangs over the edge is an object that was put there
     afterward. The overlap token is the whole difference, and it is why this
     group belongs to the sensory axis rather than to spacing.

     The cluster gap is negative on purpose. Motifs that overlap read as a pile
     of solids; motifs in a neat row read as an icon set.
     ---------------------------------------------------------------------- */
  --nb-sticker-overlap: 18px;  /* how far a seal hangs past its container edge */
  --nb-seal-size: 120px;
  --nb-motif-size: 116px;
  --nb-motif-cluster-gap: -14px;

  /* ----------------------------------------------------------------------
     PLAY: SECTION DIVIDER
     Aesthetic philosophy axis. A band boundary drawn as a rule is a rule. A
     band boundary with a strip of tape stuck across it is a seam that someone
     closed. Controlled Maximalist pays for density by making the density
     mean something, and the tape is a place to say one more true sentence.
     ---------------------------------------------------------------------- */
  --nb-tape-height: 40px;
  --nb-tape-bleed: 3%;  /* the rotated strip runs past both edges so no gap shows */
}

/* Anyone who has asked the operating system to stop animating gets a theme
   with no travel at all. The shadow still collapses, so the press still reads;
   it just stops moving. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --nb-press-travel: 0px;
    --nb-duration: 1ms;
  }
}
