@import "tailwindcss";

@source "../../../app/views/**/*.erb";
@source "../../../app/helpers/**/*.rb";
@source "../../../app/javascript/**/*.js";

/*
  Self-hosted fonts (latin subsets, variable axes). Serving them from this domain
  removes a render-blocking third-party stylesheet and its DNS+TLS round trip.
  The unicode-range matches Google's latin subset, so glyphs outside it fall back
  to the system stack exactly as they did before.
*/
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("/fonts/instrument-sans.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/fonts/jetbrains-mono.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/fonts/newsreader.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/newsreader-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
  railsengines.com design tokens.

  The palette is deliberately restricted to black, white and slate. Emphasis is
  carried by weight, size and solid black fills — never by an accent hue.
*/
@theme {
  --color-ink: #0b0c0e;
  --color-ink-soft: #1e293b;
  --color-paper: #ffffff;
  --color-fog: #f6f7f9;
  --color-mist: #eceef1;
  --color-line: #dfe3e8;
  --color-line-strong: #c3cad3;
  --color-muted: #64748b;
  --color-muted-soft: #94a3b8;

  /* Sans carries the interface. Serif carries the argument. Mono carries the code. */
  --font-sans: "Instrument Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-serif: "Newsreader", ui-serif, Georgia, serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  /* A wider type scale than the site started with: the old one topped out too early,
     so every heading carried roughly the same weight and nothing led. */
  --text-display: 4.25rem;
  --text-display--line-height: 1.02;
  --text-display--letter-spacing: -0.035em;

  --text-hero: clamp(2.75rem, 1.2rem + 5.2vw, 5.25rem);
  --text-hero--line-height: 0.98;
  --text-hero--letter-spacing: -0.04em;

  --text-section: clamp(1.75rem, 1.1rem + 1.6vw, 2.5rem);
  --text-section--line-height: 1.08;
  --text-section--letter-spacing: -0.025em;

  /* Cards used only hairlines, which read as flat at any density. */
  --shadow-card: 0 1px 2px rgb(11 12 14 / 0.04), 0 1px 3px rgb(11 12 14 / 0.03);
  --shadow-lift: 0 4px 6px -1px rgb(11 12 14 / 0.07), 0 12px 24px -8px rgb(11 12 14 / 0.10);
}

@layer base {
  html {
    -webkit-text-size-adjust: 100%;
  }

  body {
    @apply bg-paper text-ink font-sans antialiased;
    font-feature-settings: "cv05" 1, "ss01" 1;
  }

  ::selection {
    @apply bg-ink text-paper;
  }

  :focus-visible {
    @apply outline-2 outline-offset-2 outline-ink;
  }

  h1, h2, h3, h4 {
    @apply font-sans font-semibold tracking-tight text-ink;
    text-wrap: balance;
  }

  p {
    text-wrap: pretty;
  }
}

@layer components {
  /* ---- Layout ------------------------------------------------------------ */
  .shell {
    @apply mx-auto w-full max-w-6xl px-5 sm:px-8;
  }

  .shell-wide {
    @apply mx-auto w-full max-w-7xl px-5 sm:px-8;
  }

  .rule {
    @apply border-t border-line;
  }

  .section {
    @apply py-16 sm:py-20;
  }

  .eyebrow {
    @apply font-mono text-[0.6875rem] font-medium uppercase tracking-[0.18em] text-muted;
  }

  .lede {
    @apply font-serif text-lg leading-relaxed text-ink-soft sm:text-xl;
  }

  /* ---- The swap line ----------------------------------------------------- */
  /* The site's thesis in one typographic device: what you drop, what you mount. */
  .swap {
    @apply inline-flex flex-wrap items-baseline gap-x-2 gap-y-1;
  }

  .swap-from {
    @apply text-muted line-through decoration-line-strong decoration-1;
  }

  .swap-arrow {
    @apply font-mono text-muted-soft;
  }

  .swap-to {
    @apply font-mono font-medium text-ink;
  }

  /* ---- The line item ----------------------------------------------------- */
  /*
    The swap, given the shape of the thing it describes: a row on an invoice. Product
    on the left with its price struck through, the engine that replaces it on the
    right at nothing. This is the site's signature and it scales from a card to a
    full-width table row.
  */
  .line-item {
    @apply flex items-center gap-3 py-2;
  }

  .line-item-name {
    @apply min-w-0 flex-1 truncate text-ink-soft;
  }

  .line-item-price {
    @apply shrink-0 font-mono tabular-nums text-muted line-through decoration-line-strong;
  }

  .line-item-free {
    @apply shrink-0 font-mono font-medium tabular-nums text-ink;
  }

  .line-item-rule {
    @apply hidden flex-1 border-b border-dashed border-line sm:block;
  }

  /* ---- Brand marks ------------------------------------------------------- */
  /* A logo is the fastest way to recognise the thing you want off the invoice. */
  .logo-chip {
    @apply inline-flex shrink-0 items-center justify-center overflow-hidden rounded-lg
           border border-line bg-paper;
  }

  .logo-chip img {
    @apply h-full w-full object-contain;
  }

  .logo-stack > * {
    @apply -ml-2 ring-2 ring-paper first:ml-0;
  }

  /* ---- Filter chips ------------------------------------------------------ */
  .chip {
    @apply inline-flex items-center gap-1.5 whitespace-nowrap rounded-full border border-line
           bg-paper px-3 py-1.5 text-[0.8125rem] font-medium text-muted transition-colors
           hover:border-line-strong hover:text-ink;
  }

  .chip-on {
    @apply border-ink bg-ink text-paper hover:border-ink hover:text-paper;
  }

  .chip-count {
    @apply font-mono text-[0.6875rem] tabular-nums opacity-60;
  }

  /* ---- Dark band --------------------------------------------------------- */
  /* Rhythm. A page of white cards has no punctuation without one of these. */
  .band {
    @apply bg-ink text-mist;
  }

  .band h1, .band h2, .band h3 {
    @apply text-paper;
  }

  .band .eyebrow {
    @apply text-muted-soft;
  }

  /* ---- Buttons ----------------------------------------------------------- */
  /* Modifiers are composed in markup: class="btn btn-primary btn-sm". */
  .btn {
    @apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg px-4 py-2.5
           text-sm font-medium transition-colors duration-150
           disabled:cursor-not-allowed disabled:opacity-50;
  }

  .btn-primary {
    @apply bg-ink text-paper hover:bg-ink-soft;
  }

  .btn-secondary {
    @apply border border-line bg-paper text-ink hover:border-ink hover:bg-fog;
  }

  .btn-ghost {
    @apply text-muted hover:bg-fog hover:text-ink;
  }

  .btn-danger {
    @apply border border-line bg-paper text-ink hover:border-ink hover:bg-ink hover:text-paper;
  }

  .btn-sm {
    @apply px-3 py-1.5 text-[0.8125rem];
  }

  /* ---- Surfaces ---------------------------------------------------------- */
  .card {
    @apply rounded-xl border border-line bg-paper transition-colors duration-150;
  }

  .card-interactive {
    @apply hover:border-line-strong hover:shadow-[0_1px_2px_rgba(11,12,14,0.06)];
  }

  .panel {
    @apply rounded-xl border border-line bg-fog;
  }

  /* ---- Badges ------------------------------------------------------------ */
  .badge {
    @apply inline-flex items-center gap-1.5 rounded-md px-2 py-0.5 font-mono text-[0.6875rem]
           font-medium uppercase tracking-wider;
  }

  .badge-solid {
    @apply bg-ink text-paper;
  }

  .badge-outline {
    @apply border border-line text-muted;
  }

  /* ---- Forms ------------------------------------------------------------- */
  .field {
    @apply w-full rounded-lg border border-line bg-paper px-3.5 py-2.5 text-sm text-ink
           placeholder:text-muted-soft focus:border-ink focus:outline-none focus:ring-1 focus:ring-ink;
  }

  .field-error {
    @apply border-ink bg-fog;
  }

  .label {
    @apply mb-1.5 block text-sm font-medium text-ink;
  }

  .hint {
    @apply mt-1.5 text-[0.8125rem] leading-relaxed text-muted;
  }

  /* ---- Code -------------------------------------------------------------- */
  /*
    Colour appears in exactly two places on this site: syntax and category identity.
    Everywhere else stays black, white and slate. A code block is the one surface
    where colour is doing work rather than decoration — it is how you read Ruby.
  */
  .code-figure {
    @apply relative;
  }

  .code-figure-label {
    @apply absolute right-3 top-3 z-10 rounded-md bg-white/5 px-2 py-0.5 font-mono
           text-[0.625rem] uppercase tracking-wider text-muted-soft;
  }

  .code-block {
    @apply overflow-x-auto rounded-xl bg-ink p-5 font-mono text-[0.8125rem] leading-relaxed text-mist;
  }

  .code-inline {
    @apply rounded bg-mist px-1.5 py-0.5 font-mono text-[0.85em] text-ink-soft;
  }

  /* ---- Prose ------------------------------------------------------------- */
  .prose-engine {
    @apply text-[0.95rem] leading-relaxed text-ink-soft;
  }
  .prose-engine h1 { @apply mt-8 mb-3 text-2xl first:mt-0; }
  .prose-engine h2 { @apply mt-8 mb-3 text-xl first:mt-0; }
  .prose-engine h3 { @apply mt-6 mb-2 text-base first:mt-0; }
  .prose-engine p { @apply my-4 first:mt-0 last:mb-0; }
  .prose-engine ul { @apply my-4 list-disc space-y-1.5 pl-5; }
  .prose-engine ol { @apply my-4 list-decimal space-y-1.5 pl-5; }
  .prose-engine a { @apply font-medium text-ink underline decoration-line-strong underline-offset-2 hover:decoration-ink; }
  .prose-engine code { @apply rounded bg-mist px-1.5 py-0.5 font-mono text-[0.85em] text-ink; }
  .prose-engine pre { @apply my-5 overflow-x-auto rounded-xl bg-ink p-5 text-[0.8125rem] leading-relaxed text-paper; }
  .prose-engine pre code { @apply bg-transparent p-0 text-paper; }
  .prose-engine blockquote { @apply my-5 border-l-2 border-line pl-4 font-serif text-lg text-muted; }
  .prose-engine strong { @apply font-semibold text-ink; }
  .prose-engine hr { @apply my-8 border-line; }
}

/*
  Syntax theme. Pastel-bright hues on the near-black code surface, chosen together so
  that a Gemfile line reads at a glance: strings green, constants amber, symbols cyan,
  keywords violet. Class names are the ones Rouge emits.
*/
@layer components {
  .code-block .c, .code-block .c1, .code-block .cm, .code-block .cs, .code-block .cp {
    @apply text-muted italic;
  }

  .code-block .k, .code-block .kd, .code-block .kn, .code-block .kp, .code-block .kr,
  .code-block .kv, .code-block .o, .code-block .ow {
    color: #c4b5fd; /* violet — keywords and operators */
  }

  .code-block .s, .code-block .s1, .code-block .s2, .code-block .sb, .code-block .sh,
  .code-block .si, .code-block .sx, .code-block .sr, .code-block .dl {
    color: #86efac; /* green — strings */
  }

  .code-block .nc, .code-block .nn, .code-block .no, .code-block .kt, .code-block .nb {
    color: #fcd34d; /* amber — constants, classes, modules */
  }

  .code-block .ss {
    color: #67e8f9; /* cyan — symbols, the shape of Ruby */
  }

  .code-block .nf, .code-block .nd, .code-block .fm {
    color: #93c5fd; /* blue — method names */
  }

  .code-block .m, .code-block .mi, .code-block .mf, .code-block .mh, .code-block .il,
  .code-block .kc {
    color: #fdba74; /* orange — numbers and literals */
  }

  .code-block .nv, .code-block .vi, .code-block .vg, .code-block .n, .code-block .nl {
    @apply text-mist;
  }

  .code-block .p, .code-block .pi {
    @apply text-muted-soft;
  }

  .code-block .gd { color: #fca5a5; }
  .code-block .gi { color: #86efac; }
  .code-block .err { @apply text-mist; }
}

@layer utilities {
  /* Hero reveal. One orchestrated moment on load, nothing else on the page moves. */
  @keyframes rise {
    from { opacity: 0; transform: translateY(0.5rem); }
    to   { opacity: 1; transform: none; }
  }

  .rise {
    animation: rise 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  @media (prefers-reduced-motion: reduce) {
    .rise { animation: none; }
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      transition-duration: 0.01ms !important;
    }
  }

  .no-scrollbar::-webkit-scrollbar { display: none; }
  .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
}
