/* =========================================================
   Design tokens, fonts, reset and base typography.

   Same house identity as Skull Solutions (see the asset library's
   assets/README.md): paper and porcelain grounds, one ink, and one
   soft accent per brand. SkullSploit's accent is plum, and the rule
   the whole family keeps is that the accent lives in surfaces, type
   and interface — never on the mascot's face or its ink line.

   The site used to be greyscale and dark-first. It is the paper
   scheme now, because the two brands are one house and a visitor
   crossing from skullsolutions.com should arrive somewhere that is
   recognisably the same drawing board. What stays is the night: the
   closing slab, the footer and the findings panel are dark, which is
   where the offensive half of the family gets its temper from.

   Everything in styles.css, responsive.css and motion.css is written
   against these names. The `Aliases` block at the end is what lets
   chat.css — shared byte for byte with the parent site — keep working
   unchanged.
   ========================================================= */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("/fonts/cormorant-garamond.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Cormorant Garamond";
  src: url("/fonts/cormorant-garamond-italic.woff2") format("woff2");
  font-weight: 500;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "Karla";
  src: url("/fonts/karla.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Karla";
  src: url("/fonts/karla-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;

  /* ---------- Grounds ---------- */
  --paper: #f2efeb;
  --porcelain: #fbf9f7;
  --ink: #17141c;
  --night: #1b1721;
  --night-deep: #12101a;

  /* ---------- Text ---------- */
  --text: var(--ink);
  --text-2: #3d3743; /* body copy: 10.0:1 on paper */
  --text-3: #625b68; /* labels and meta: 5.7:1 on paper */
  --on-night: #efe9ef;
  --on-night-2: #bdb4c2; /* 8.8:1 on night */

  /* ---------- Lines ---------- */
  --rule: rgb(23 20 28 / 0.14);
  --rule-mid: rgb(23 20 28 / 0.28);
  --rule-strong: var(--ink);
  --rule-night: rgb(239 233 239 / 0.16);

  /* ---------- Brand accents ----------
     Plum is this brand's, so it is the one with a full set: a fill at the
     identity's 0.70 lightness, two washes for large surfaces, an ink that
     passes contrast as text on paper, and a light tint for text on night.
     Periwinkle is kept because the parent company is named on nearly every
     page, and the hand-off reads better when the other half of the house has
     its own colour rather than borrowing this one. */
  --sploit: #bd94c3;
  --sploit-wash: #f0e7f2;
  --sploit-tint: #f6f0f7;
  --sploit-ink: #6f4a75; /* 6.4:1 on paper */
  --sploit-light: #d8b9dd; /* on night */

  --sol: #8f9bd0;
  --sol-wash: #e3e6f3;
  --sol-ink: #46508a; /* 6.6:1 on paper */

  /* The accent, by role rather than by name. Components use these, so a
     re-skin is four lines rather than a search across the stylesheet. */
  --accent: var(--sploit);
  --accent-wash: var(--sploit-wash);
  --accent-tint-soft: var(--sploit-tint);
  --accent-ink: var(--sploit-ink);
  --accent-on-night: var(--sploit-light);

  /* ---------- Status ----------
     Always paired with a word (see status() in ui.mjs), never colour alone.
     This site says "high", "critical" and "closed" a good deal more than the
     parent does, so --bad is the one that has to stay legible on both grounds. */
  --ok: #3f7a5a;
  --warn: #a8701d;
  --bad: #b5483d;
  --bad-on-night: #e8897e;
  --info: var(--sploit-ink);

  /* ---------- Type ---------- */
  --font-display: "Cormorant Garamond", "Cormorant", Garamond, "Times New Roman", serif;
  --font-body: "Karla", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* Karla sets small; the display face sets smaller still at the same size,
     because Cormorant's x-height is low. The scale compensates. */
  --step--2: 0.75rem;
  --step--1: 0.875rem;
  --step-0: 1.0625rem;
  --step-1: clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
  --step-2: clamp(1.5rem, 1.3rem + 0.9vw, 2rem);
  --step-3: clamp(1.875rem, 1.5rem + 1.8vw, 2.875rem);
  --step-4: clamp(2.375rem, 1.7rem + 3.2vw, 4.125rem);
  --step-5: clamp(2.875rem, 1.6rem + 6vw, 6.25rem);

  /* ---------- Space & layout ---------- */
  --container: 76rem;
  --container-narrow: 52rem;
  --gutter: clamp(1rem, 3.5vw, 2rem);
  --section-space: clamp(4rem, 9vw, 7.5rem);
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4.5rem;

  /* Engineering drawings, not app cards: corners are nearly square. */
  --radius: 2px;
  --radius-pill: 999px;

  /* The button shadow is a printed offset, not a blur. */
  --offset: 3px 3px 0 var(--ink);
  --offset-hover: 5px 5px 0 var(--ink);
  --shadow-soft: 0 1px 0 rgb(23 20 28 / 0.04), 0 18px 40px -28px rgb(23 20 28 / 0.35);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* Dot grid for "engineering paper" surfaces. */
  --grid-dot: radial-gradient(circle at 1px 1px, rgb(23 20 28 / 0.14) 1px, transparent 1.4px);
  --grid-dot-night: radial-gradient(circle at 1px 1px, rgb(239 233 239 / 0.12) 1px, transparent 1.4px);
  --grid-size: 22px 22px;

  /* Paper grain, inlined as SVG so it costs no request. Kept from the previous
     scheme, at a fraction of the weight: on a near-white ground it multiplies in
     as the tooth of the paper rather than lifting specks out of black. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)' opacity='0.5'/%3E%3C/svg%3E");
  --grain-blend: multiply;
  --grain-opacity: 0.05;

  /* The mark as a mask: the glyph supplies the shape and CSS supplies the
     colour, so one asset works on any surface. evenodd is what keeps the eyes
     cut out of the silhouette instead of filled.

     Same geometry as skullMark() in src/components/icons.mjs. The two are the
     same drawing in two forms the platform cannot share, so a change to the
     mascot is a change in both places. */
  --skull-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath fill='%23000' fill-rule='evenodd' d='M50 8 C24 8 10 26 10 48 C10 64 20 76 32 76 L34 76 L34 83 C34 88 43 88 43 83 L43 76 L45.5 76 L45.5 86 C45.5 91 54.5 91 54.5 86 L54.5 76 L57 76 L57 83 C57 88 66 88 66 83 L66 76 L68 76 C80 76 90 64 90 48 C90 26 76 8 50 8 Z M44.8 45 a10.8 12.4 0 0 1-21.6 0 10.8 12.4 0 0 1 21.6 0 Z M76.8 45 a10.8 12.4 0 0 1-21.6 0 10.8 12.4 0 0 1 21.6 0 Z'/%3E%3C/svg%3E");

  /* The mascot's teeth, as a repeating edge. Three rounded tabs hanging from a
     bar, the same proportions as the teeth on the glyph. Used as a mask, so the
     colour comes from background-color on whatever paints it. */
  --teeth: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='22' viewBox='0 0 72 22'%3E%3Cpath d='M0 0H72V6H0Z M4 5H20V12A8 8 0 0 1 4 12Z M28 5H44V15A8 8 0 0 1 28 15Z M52 5H68V12A8 8 0 0 1 52 12Z'/%3E%3C/svg%3E");

  /* ---------- Aliases ----------
     chat.css is shared with the parent site byte for byte and is written
     against these names, as are the reveal keyframes in motion.css. Repointing
     them here is what kept both files out of this re-skin. */
  --bg: var(--porcelain);
  --bg-inset: var(--paper);
  --fg: var(--ink);
  --muted: var(--text-2);
  --faint: var(--text-3);
  --line: var(--rule-mid);
  --line-soft: var(--rule);
  --line-strong: var(--ink);
  --invert-bg: var(--ink);
  --invert-fg: var(--porcelain);
  --accent-tint: var(--sploit-tint);
  --cta-bg: var(--night);
  --cta-fg: var(--on-night);
  --step-000: var(--step--2);
  --step-00: var(--step--1);
  --font-sans: var(--font-body);
  --font-serif: var(--font-display);
  --shadow-sm: 0 6px 18px -10px rgb(23 20 28 / 0.25);
  --shadow-md: 0 22px 48px -20px rgb(23 20 28 / 0.35);
  --shadow-lift: 0 30px 60px -28px rgb(23 20 28 / 0.45);
  --shadow-rim: inset 0 1px 0 rgb(251 249 247 / 0.5);
  --rule-fade:
    linear-gradient(to right, transparent 0%, var(--rule) 16%, var(--rule) 84%, transparent 100%);
}

/* ---------- Reset ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body,
h1,
h2,
h3,
h4,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

ul[role="list"],
ol[role="list"] {
  padding: 0;
  list-style: none;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(5.5rem + env(safe-area-inset-top));
}

img,
svg {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

table {
  border-collapse: collapse;
}

/* ---------- Base ---------- */

body {
  min-height: 100vh;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

/* Paper grain over the whole page. It sits on top rather than behind, because
   the cards, the header and the night slabs all paint their own opaque
   background and grain underneath them would show through in patches. It never
   takes a pointer event, so nothing below it changes behaviour. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  background-image: var(--grain);
  background-size: 220px 220px;
  opacity: var(--grain-opacity);
  mix-blend-mode: var(--grain-blend);
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.01em;
  text-wrap: balance;
  color: var(--ink);
}

h1 em,
h2 em,
h3 em {
  font-style: italic;
  font-weight: 500;
}

p {
  text-wrap: pretty;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}

a:hover {
  text-decoration-color: var(--accent);
}

strong {
  font-weight: 700;
}

::selection {
  background: var(--accent-wash);
  color: var(--ink);
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 1px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }

  /* Hover lift is a movement, not a state change — drop it entirely rather than
     make it instant. The colour and border changes still carry the state. */
  .btn:hover,
  .btn:active {
    transform: none;
  }
}
