/* ============================================================
   Good Omens — Foundations
   Black-first, neo-grotesque, high-contrast, no chrome.
   ============================================================ */


:root {
  /* ----------------------------------------------------------
     1. CORE PALETTE — black is the key color
     ---------------------------------------------------------- */
  --ink:           #161616;   /* the brand black — softened a hair
                                 off #000 so it reads as ink on
                                 stock, not text on a screen.    */
  --ink-true:      #000000;   /* reserved: the chop, the wordmark */
  --paper:         #FFFFFF;   /* pure white — cards and panels    */
  --paper-warm:    #FAF8F3;   /* IVORY — the page background      */

  /* Neutral ramp — warmed by a whisper so it sits on ivory.
     Still reads neutral; chroma stays under 0.008.              */
  --n-50:          #F5F3EE;
  --n-100:         #EDEAE3;
  --n-200:         #E4E0D6;
  --n-300:         #C4BFB4;
  --n-400:         #8E8A81;
  --n-500:         #6E6A61;
  --n-600:         #3E3B36;
  --n-700:         #272522;
  --n-800:         #1C1A18;
  --n-900:         #0F0E0D;

  /* ---- NOTABLE SURFACE ------------------------------------
     There is no accent colour in this system — warmth lives in
     the paper and personality in the typeface. What components
     still need is a surface that reads as "this one matters":
     one step warmer than the page, with its own hairline.
     Use these instead of reaching for --n-50.                  */
  --surface-notable:      #F3F0E8;
  --surface-notable-line: #E0DBCF;
  --surface-notable-hover:#EDE9DF;

  /* Sparing semantics — system states only. Never decoration.  */
  --signal-green:  #1F6B41;
  --signal-amber:  #8A5A08;
  --signal-red:    #9B1C17;
  --signal-blue:   #1B4DCC;

  /* ----------------------------------------------------------
     2. SEMANTIC SURFACE / TEXT TOKENS
     ---------------------------------------------------------- */
  --bg:            var(--paper-warm);
  --bg-alt:        var(--paper);
  --bg-inverse:    var(--ink);
  --bg-muted:      var(--n-50);

  --fg:            var(--ink);
  --fg-muted:      var(--n-500);
  --fg-subtle:     var(--n-400);
  --fg-inverse:    var(--paper);

  --border:        var(--n-200);
  --border-strong: var(--ink);
  --rule:          var(--n-100);

  --focus-ring:    var(--ink);

  /* ----------------------------------------------------------
     3. TYPE FAMILIES
     Substitution flag: Inter stands in for the Söhne/Neue-Haas-
     style display sans seen in the wordmark. Provide a real
     family file via /fonts to override.
     ---------------------------------------------------------- */
  --font-sans:     "Inter", "Söhne", "Neue Haas Grotesk", -apple-system,
                   BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial,
                   sans-serif;
  --font-mono:     "JetBrains Mono", ui-monospace, "SF Mono", Menlo,
                   Consolas, monospace;
  --font-display:  var(--font-sans);

  /* The one editorial voice. Libre Caslon Text is used in EXACTLY
     one role — pull quotes and testimonials. Never headings,
     never body, never UI. The restraint is the point: the moment
     it appears in a second role the effect collapses.          */
  --font-quote:    "Libre Caslon Text", Georgia, "Times New Roman", serif;

  /* ----------------------------------------------------------
     4. TYPE SCALE — display gets tight, body gets generous
     ---------------------------------------------------------- */
  --fs-xs:    12px;
  --fs-sm:    14px;
  --fs-base:  16px;
  --fs-md:    18px;
  --fs-lg:    20px;
  --fs-xl:    24px;
  --fs-2xl:   32px;
  --fs-3xl:   44px;
  --fs-4xl:   60px;
  --fs-5xl:   84px;
  --fs-6xl:   120px;

  --lh-tight:  0.95;  /* @kind other */
  --lh-snug:   1.05;  /* @kind other */
  --lh-normal: 1.4;   /* @kind other */
  --lh-loose:  1.6;   /* @kind other */

  --tr-tight:  -0.04em;   /* @kind other */
  --tr-snug:   -0.02em;   /* @kind other */
  --tr-normal: -0.005em;  /* @kind other */
  --tr-wide:    0.08em;   /* @kind other */
  --tr-mono:    0;        /* @kind other */

  /* ----------------------------------------------------------
     5. SPACING / RADII / SHADOWS
     ---------------------------------------------------------- */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  24px;
  --s-6:  32px;
  --s-7:  48px;
  --s-8:  64px;
  --s-9:  96px;
  --s-10: 128px;

  /* Sharp 90° corners are the brand. There is no radius scale — the
     only two legal values are 0 and a full circle. A 4/8/12px ramp
     was removed because it existed only to be ignored: soft radii
     read as off-the-shelf and are explicitly off-limits.          */
  --r-none:   0;     /* @kind radius */
  --r-pill:   999px; /* @kind radius */

  /* ---- 2.5D "stamp" system -------------------------------
     Hard, blur-less offset shadows give surfaces a printed,
     letterpress-on-paper feel. Distance scales with elevation.
     Always paired with a 1px hairline so the edge stays crisp.

     TWO intents, one colour decision each — do not add a third:
       --stamp-ink       a stamp on a PAPER surface. This is the
                         brand default and the canonical gesture.
       --stamp-ink-fill  a stamp under a FILLED control, where
                         ink-on-ink would merge into one shape.
     The --stamp-* scale below derives from --stamp-ink, so the
     colour is decided in exactly one place.                    */
  --stamp-ink:      var(--ink);
  --stamp-ink-fill: var(--n-400);

  --stamp-xs:  2px 2px 0 var(--stamp-ink);
  --stamp-sm:  4px 4px 0 var(--stamp-ink);
  --stamp-md:  8px 8px 0 var(--stamp-ink);
  --stamp-lg: 12px 12px 0 var(--stamp-ink);

  /* Inverse stamp — used on dark surfaces.                    */
  --stamp-inv-sm: 4px 4px 0 var(--paper);
  --stamp-inv-md: 8px 8px 0 var(--paper);

  /* ---- Engraved / letterpress detail ---------------------
     A 1px highlight inside dark surfaces, a 1px shade inside
     light ones — reads as a struck plate edge.                */
  --engrave-light: inset 0 1px 0 rgba(255,255,255,0.06),
                   inset 0 -1px 0 rgba(0,0,0,0.04);  /* @kind shadow */
  --engrave-dark:  inset 0 1px 0 rgba(255,255,255,0.10),
                   inset 0 -1px 0 rgba(0,0,0,0.55);  /* @kind shadow */

  /* Soft shadows are reserved for true floating layers only
     (menus, toasts, modals). Most surfaces use --stamp-*.     */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 16px rgba(0,0,0,0.08);
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.12);
  --shadow-inset-rule: inset 0 -1px 0 var(--rule);  /* @kind shadow */

  /* Hairline border — our default chrome.                     */
  --hairline:  1px solid var(--border);             /* @kind other */
  --hairline-strong: 1px solid var(--border-strong);/* @kind other */

  /* ----------------------------------------------------------
     6. MOTION
     ---------------------------------------------------------- */
  --ease-out:    cubic-bezier(0.2, 0.8, 0.2, 1);   /* @kind other */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);   /* @kind other */
  --dur-fast:    120ms;  /* @kind other */
  --dur-base:    260ms;  /* @kind other */
  --dur-slow:    360ms;  /* @kind other */
  --dur-wipe:    420ms;  /* @kind other */

  /* ----------------------------------------------------------
     7. APP-SURFACE TOKENS
     Things web apps need that marketing sites don't.
     ---------------------------------------------------------- */

  /* Surfaces — light theme (default). Dark theme overrides below. */
  --surface:        var(--paper);          /* the card / panel default     */
  --surface-2:      var(--paper-warm);     /* alt panel — settings, sidebar */
  --surface-sunken: var(--n-50);           /* below-ground / input fill    */
  --surface-raised: var(--paper);          /* floating menus, popovers     */
  --hover-bg:       var(--n-50);           /* subtle hover wash            */
  --selected-bg:    var(--surface-notable);/* selected row, pressed tab    */
  --overlay-scrim:  rgba(0,0,0,0.45);      /* modal backdrop               */

  /* The chop is a transparent PNG with BLACK artwork, so it needs inverting
     on any dark backdrop or it disappears. This token covers the theme-level
     case; for an ink surface inside a light theme (an inverse hero, an auth
     slab) pass the component's own `inverse` flag instead.               */
  --chop-filter:    none;                  /* @kind other */

  /* ----------------------------------------------------------
     8. LAYOUT — breakpoints, container widths, z-index
     ---------------------------------------------------------- */
  --bp-sm:     480px;   /* @kind other */
  --bp-md:     768px;   /* @kind other */
  --bp-lg:    1024px;   /* @kind other */
  --bp-xl:    1280px;   /* @kind other */
  --bp-2xl:   1440px;   /* @kind other */

  --container-page:    1440px;  /* @kind spacing */
  --container-app:     1280px;  /* @kind spacing */
  --container-reading:  640px;  /* @kind spacing */
  --container-form:     420px;  /* @kind spacing */

  --touch-target:        44px;  /* @kind spacing */
  --control-height:      40px;  /* @kind spacing */
  --control-height-sm:   32px;  /* @kind spacing */
  --control-height-lg:   48px;  /* @kind spacing */

  --z-base:        1;   /* @kind other */
  --z-sticky:    100;   /* @kind other */
  --z-dropdown:  200;   /* @kind other */
  --z-overlay:   300;   /* @kind other */
  --z-drawer:    400;   /* @kind other */
  --z-modal:     500;   /* @kind other */
  --z-toast:     600;   /* @kind other */
  --z-tooltip:   700;   /* @kind other */

  /* ----------------------------------------------------------
     9. STATE / FEEDBACK
     ---------------------------------------------------------- */
  --focus-ring-width:  2px;  /* @kind spacing */
  --focus-ring-offset: 2px;  /* @kind spacing */

  /* Skeleton shimmer — slow, low-contrast, on-brand. */
  --skeleton-bg:   var(--n-100);
  --skeleton-glint: var(--n-50);

  /* Data viz — five distinguishable mono-friendly hues, ordered for
     legibility on light backgrounds. Use sparingly.                       */
  --viz-1: var(--ink);
  --viz-2: #6E6A61;
  --viz-3: #1B4DCC;
  --viz-4: #8A5A08;
  --viz-5: #0E7A3D;
}

/* ============================================================
   THEME — light (default) + dark
   Toggle via `<html data-theme="dark">` or `<body data-theme="dark">`.
   Light is the brand default; dark is for product surfaces and PWAs.
   ============================================================ */

:root,
[data-theme="light"] {
  color-scheme: light;
}

[data-theme="dark"] {
  color-scheme: dark;

  /* Surfaces flip — paper becomes ink, neutrals invert. */
  --bg:            var(--ink);
  --bg-alt:        #0A0A0A;
  --bg-inverse:    var(--paper);
  --bg-muted:      #141414;

  --fg:            #F7F5F0;
  --fg-muted:      #A8A49B;
  --fg-subtle:     #767268;
  --fg-inverse:    var(--ink);

  --border:        #262626;
  --border-strong: var(--paper);
  --rule:          #1A1A1A;

  --focus-ring:    var(--paper);

  --surface:        #0A0A0A;
  --surface-2:      #141414;
  --surface-sunken: #050505;
  --surface-raised: #1A1A1A;
  --hover-bg:       #1A1A1A;
  --selected-bg:    #2A170C;

  /* Notable surface inverts to a warm-lit plate on dark. */
  --surface-notable:      #201E1B;
  --surface-notable-line: #302D28;
  --surface-notable-hover:#262320;
  --overlay-scrim:  rgba(0,0,0,0.65);
  --chop-filter:    invert(1);             /* @kind other */

  /* Stamps flip to paper on dark; the fill variant stays neutral so it
     still reads under both light and dark control fills. */
  --stamp-ink:      var(--paper);
  --stamp-ink-fill: var(--n-500);

  --skeleton-bg:    #1A1A1A;
  --skeleton-glint: #262626;

  /* Soft shadows get more weight on dark, otherwise vanish. */
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.5);
  --shadow-md: 0 4px 16px rgba(0,0,0,0.5);
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.6);

  /* Signal hues stay legible — slightly brighter on dark. */
  --signal-green: #2EA85C;
  --signal-amber: #D9B14A;
  --signal-red:   #E86B60;
  --signal-blue:  #4A78E0;

  /* Data viz — flipped to read on dark. */
  --viz-1: #FFFFFF;
  --viz-2: #A6A6A6;
  --viz-3: #4A78E0;
  --viz-4: #D9B14A;
  --viz-5: #2EA85C;
}

/* Dark mode is OPT-IN — set `<html data-theme="dark">` (or on <body>).
   The brand is light-first; we deliberately do NOT auto-flip on the OS
   `prefers-color-scheme` preference, so a light-first marketing page stays
   light on a dark-mode machine. Product surfaces that want to follow the OS
   should set data-theme from their own matchMedia listener. */

/* Reduced motion — strip the easing motion to honor the system pref.    */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   SEMANTIC TYPE STYLES
   Use these classes (or @extend) instead of rolling new sizes.
   ============================================================ */

html { font-family: var(--font-sans); color: var(--fg); background: var(--bg); }
body { font-size: var(--fs-base); line-height: var(--lh-normal); -webkit-font-smoothing: antialiased; }

.go-display,
.go-h0 {
  font-family: var(--font-display);
  font-size: clamp(60px, 9vw, 120px);
  font-weight: 800;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-tight);
  color: var(--fg);
}

.go-h1 {
  font-size: var(--fs-4xl);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-tight);
}

.go-h2 {
  font-size: var(--fs-3xl);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-snug);
}

.go-h3 {
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-snug);
}

.go-h4 {
  font-size: var(--fs-xl);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: var(--tr-normal);
}

.go-lede {
  font-size: var(--fs-lg);
  font-weight: 400;
  line-height: var(--lh-loose);
  color: var(--fg-muted);
  letter-spacing: var(--tr-normal);
  max-width: 60ch;
}

.go-body {
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: var(--lh-loose);
  color: var(--fg);
}

.go-body-sm {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--fg);
}

.go-caption {
  font-size: var(--fs-xs);
  line-height: 1.4;
  color: var(--fg-muted);
}

.go-eyebrow {
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* Quieter eyebrow — for a section that already carries emphasis.  */
.go-eyebrow-quiet { color: var(--fg-subtle); }

/* ---- NOTABLE SURFACE (the D2 accent rule) -------------------
   Use instead of a plain --n-50 fill when a surface means
   "this matters": callouts, featured cards, selected rows.     */
.go-notable {
  background: var(--surface-notable);
  border: 1px solid var(--surface-notable-line);
  color: var(--fg);
}
.go-notable-row {
  background: var(--surface-notable);
  box-shadow: inset 0 -1px 0 var(--surface-notable-line);
}
.go-chip-accent {
  background: var(--surface-notable);
  color: var(--fg-muted);
  border: 1px solid var(--surface-notable-line);
}
/* Full-strength ink fill — the emphatic surface.                */
.go-accent-fill { background: var(--ink); color: var(--paper-warm); }
.go-accent-rule { background: var(--ink); }

.go-mono {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: var(--tr-mono);
}

.go-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.go-link:hover { opacity: 0.65; }

a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--fg-muted); }

/* ---- PREMIUM DETAIL PASS -----------------------------------
   Small optical corrections that separate "clean" from "expensive".
   None of these change a colour or a size — they change the fit. */

/* Numerals align in tables, stats, and prices — the single most
   noticeable "someone cared" detail in a data-heavy UI.
   NOTE: numerals need MORE weight than the lettering beside them.
   At display sizes a 600 digit looks anaemic next to 600 letters —
   set figures a step heavier and always at full --ink.           */
table, .go-mono, .go-stat, [data-numeric] { font-variant-numeric: tabular-nums; }
.go-stat, [data-numeric] { font-weight: 700; color: var(--ink); }

/* Display type at scale needs less tracking than the browser gives
   it, and no ligature surprises.                                */
.go-display, .go-h0, .go-h1, .go-h2 { font-feature-settings: "kern" 1, "liga" 1; font-optical-sizing: auto; }

/* Hanging punctuation and true quotes in reading copy.          */
.go-body, .go-lede, p { hanging-punctuation: first last; }

/* Grayscale-safe image treatment — photography sits on ivory
   without looking pasted on.                                    */
.go-photo { filter: grayscale(1) contrast(1.04); background: var(--n-100); }

/* ---- THE QUOTE ---------------------------------------------
   The system's only serif, in its only role. Libre Caslon Text
   is drawn for small body sizes, so its sidebearings are
   generous — at display size it needs negative tracking and a
   matching drop in leading, or the block reads wide instead of
   tight. 400 weight only; 700 would out-shout the headline it
   supports.                                                    */
.go-quote {
  font-family: var(--font-quote);
  font-weight: 400;
  font-size: clamp(20px, 2.2vw, 27px);
  line-height: 1.34;
  letter-spacing: -0.026em;
  color: var(--ink);
  max-width: 34ch;
  font-kerning: normal;
  font-feature-settings: "kern" 1, "liga" 1;
  text-wrap: pretty;
  margin: 0;
}
.go-quote-attr {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-subtle);
  margin-top: var(--s-5);
}

/* ---- LETTERPRESS CARD EDGE ---------------------------------
   Under a millimetre of implied stock thickness on white cards
   sitting on ivory: a 1px white highlight along the top inner
   edge, a 4.5%-ink shade along the bottom. No blur, ever.
   Do not combine with --stamp-* on the same surface.          */
.go-press {
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 #FFFFFF,
              inset 0 -1px 0 rgba(22,22,22,0.045),
              0 1px 0 rgba(22,22,22,0.03);
}
[data-theme="dark"] .go-press {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06),
              inset 0 -1px 0 rgba(0,0,0,0.5),
              0 1px 0 rgba(0,0,0,0.4);
}

/* ---- THE WIPE ----------------------------------------------
   Hover fills sweep in from the left rather than cross-fading.
   A fade is a state change; a wipe is a gesture. 420ms.
   Buttons, nav links, and card hovers ONLY — never form inputs
   or table rows, where a slow response reads as broken.       */
.go-wipe {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color 420ms var(--ease-in-out);
}
.go-wipe::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 420ms var(--ease-in-out);
  z-index: -1;
}
.go-wipe:hover { color: var(--paper-warm); }
.go-wipe:hover::before { transform: scaleX(1); }
/* Inverse wipe — dark surfaces sweep to paper. */
.go-wipe-inverse::before { background: var(--paper-warm); }
.go-wipe-inverse:hover { color: var(--ink); }

/* ---- NUMBERED INDEX ROWS -----------------------------------
   The 01 — 02 — 03 device, formalised. Hairline-separated rows,
   mono index in a fixed column at subtle contrast. Ordered
   sequences only; never an unordered list.                    */
.go-index { display: flex; flex-direction: column; }
.go-index > * {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  box-shadow: inset 0 -1px 0 var(--border);
}
.go-index > *:last-child { box-shadow: none; }
.go-index > * > :first-child {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  color: var(--fg-subtle);
  font-variant-numeric: tabular-nums;
}

/* Hover / press conventions ---------------------------------- */
.go-hover-fade  { transition: opacity var(--dur-fast) var(--ease-out); }
.go-hover-fade:hover { opacity: 0.7; }
.go-press-shrink:active { transform: scale(0.98); }


/* ============================================================
   TEXT-WRAP ROBUSTNESS  (system-wide safety net)
   Fixes the three recurring layout failures:
   • awkward line breaks with space still on the line
       -> text-wrap: balance (headings) / pretty (body)
   • long unbroken tokens (URLs, emails, IDs, code) pushing past a
     fixed box and getting clipped  ->  overflow-wrap: break-word
   • flex / grid children that refuse to shrink below their content
       ->  min-width: 0 on the text roles
   These are additive; they never change a size, colour, or family.
   ============================================================ */

/* Element-level defaults — catch semantic markup in every kit,
   including the JSX website/app components that use real tags. */
h1, h2, h3, h4, h5, h6 { text-wrap: balance; overflow-wrap: break-word; }
p, li, blockquote, dd, dt, figcaption { text-wrap: pretty; overflow-wrap: break-word; }

/* Headline roles — balance keeps a multi-line title even instead of
   dropping a single orphan word onto its own line. */
.go-display, .go-h0, .go-h1, .go-h2, .go-h3, .go-h4 {
  text-wrap: balance;
  overflow-wrap: break-word;
  min-width: 0;
}

/* Reading roles — pretty prevents a lone last-line word (widow). */
.go-lede, .go-body, .go-body-sm, .go-caption, .go-eyebrow {
  text-wrap: pretty;
  overflow-wrap: break-word;
  min-width: 0;
}
