/* ==========================================================================
   carcara.seixas.dev — custom tweaks on top of Tailwind

   Tailwind does the layout work (compiled to tailwind.css, which is linked
   BEFORE this file). This file only holds the few things that are awkward to
   express as utility classes: the shared card surface, the hero grid texture,
   entrance animations, focus styling and the command blocks on /install.

   Unlike tailwind.css, this file is hand-written and needs no build step —
   edit it and reload.

   Deliberately a near-copy of poraque.seixas.dev/static/css/style.css and
   calango.seixas.dev/static/css/style.css. Everything through the scrollbar
   section is byte-identical on purpose, so the four sites keep looking like
   one family; the parts unique to this product (.code-block, .card-warn,
   .wordmark) are added at the end.
   ========================================================================== */

:root {
  --surface: #ffffff;
  --surface-border: #e2e8f0;      /* slate-200 */
  --grid-line: rgba(15, 23, 42, 0.055);
  /* Reuses the token from assets/tailwind.css @theme, so the accent colour is
     defined in exactly one place. The literal is a fallback in case this file
     is ever loaded without the compiled stylesheet. */
  --accent: var(--color-brand-700, #7a4d06);
}

/* --------------------------------------------------------------------------
   Dark theme: the umber ramp

   The templates say `dark:bg-slate-900`, `dark:border-slate-800`,
   `dark:text-slate-400` in a few hundred places, and Tailwind v4 compiles each
   of those to `var(--color-slate-N)`. Redefining those variables here — under
   `.dark` only, so light mode keeps the neutral slate — repaints every dark
   surface in one place instead of rewriting every template.

   Unlike the brand ramp, this stays deliberately desaturated: a paragraph set
   in this scale should read as "warm grey", not "gold text". 950 is the page
   background, #150d00 — one shade below the palette's own #201400, which
   stays in the scale as brand-950. Contrast on that background: 400 is
   7.2:1 (body text), 500 is 4.9:1 (the small muted notes), 300 is 10:1
   (emphasised body copy).

   Unlayered, so it beats Tailwind's `@layer theme` regardless of source order.
   -------------------------------------------------------------------------- */

.dark {
  --color-slate-50:  #fbf6ec;
  --color-slate-100: #f3e8d0;
  --color-slate-200: #e6d3a8;
  --color-slate-300: #d3b87c;
  --color-slate-400: #b99a5c;
  --color-slate-500: #9a7c48;
  --color-slate-600: #7c6238;
  --color-slate-700: #5f4a2a;
  --color-slate-800: #43331d;
  --color-slate-900: #2c2110;
  --color-slate-950: #150d00;

  --surface: rgba(44, 33, 16, 0.5);   /* slate-900 / 50 */
  --surface-border: #43331d;          /* slate-800 */
  --grid-line: rgba(255, 204, 0, 0.055);
  --accent: var(--color-brand-400, #ffcc00);
}

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

body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background-color: color-mix(in srgb, var(--accent) 22%, transparent);
}

/* A visible, consistent focus ring for keyboard users on every interactive
   element, without showing it on mouse clicks. */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 0.5rem;
}

/* --------------------------------------------------------------------------
   Card surface
   Used by .card throughout the templates so every panel shares one treatment.
   -------------------------------------------------------------------------- */

.card {
  background-color: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: 1rem;
  transition: border-color 200ms ease, box-shadow 200ms ease, transform 200ms ease;
}

.card:hover {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--surface-border));
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 8px 24px -12px rgba(15, 23, 42, 0.18);
}

/* Only lift cards that are themselves links or contain a stretched link. */
a.card:hover,
.card:has(.link-cover):hover {
  transform: translateY(-2px);
}

.dark .card:hover {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
}

/* Makes a single <a> cover its nearest positioned ancestor, so a whole card is
   clickable while the DOM keeps exactly one link (better for screen readers). */
.card:has(.link-cover) { position: relative; }

.link-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

/* --------------------------------------------------------------------------
   Hero grid texture

   The mask lives on a pseudo-element, not on .bg-grid itself. A mask applies to
   an element AND everything inside it, so masking the section faded out the
   headline, the paragraph and the buttons along with the texture — the hero
   read as if it were behind fog. Only the texture should fade.

   `isolation: isolate` keeps the z-index: -1 layer inside the section, above
   the section's own background and below its content.
   -------------------------------------------------------------------------- */

.bg-grid {
  position: relative;
  isolation: isolate;
}

.bg-grid::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  /* Fade the grid out towards the bottom so it never fights the content. */
  mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 25%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 25%, transparent 90%);
}

/* --------------------------------------------------------------------------
   Entrance animation
   Staggered via .reveal-1 … .reveal-5 on the hero elements.
   -------------------------------------------------------------------------- */

@keyframes reveal-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal {
  animation: reveal-up 620ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.reveal-1 { animation-delay: 70ms; }
.reveal-2 { animation-delay: 140ms; }
.reveal-3 { animation-delay: 210ms; }
.reveal-4 { animation-delay: 280ms; }
.reveal-5 { animation-delay: 350ms; }

/* --------------------------------------------------------------------------
   Scrollbar
   -------------------------------------------------------------------------- */

@media (min-width: 768px) {
  * {
    scrollbar-width: thin;
    scrollbar-color: #cbd5e1 transparent;
  }
  .dark * {
    scrollbar-color: #5f4a2a transparent;
  }
}

/* ==========================================================================
   Carcará-only, from here down
   ========================================================================== */

/* --------------------------------------------------------------------------
   Wordmark
   Two PNGs — the shipped logo/logo_light.png and logo/logo_dark.png, trimmed
   to their own ink — swapped by the theme class rather than
   prefers-color-scheme, so the header toggle moves the logo too. The aspect
   ratio is fixed here so the header does not jump while the image loads.
   -------------------------------------------------------------------------- */

.wordmark {
  aspect-ratio: 4.2 / 1;
  width: auto;
  object-fit: contain;
}

/* --------------------------------------------------------------------------
   Warning cards
   Used on /hardware for the honestly-labelled gaps (error mitigation is a
   stub, forces/relaxation is known-broken) — a left rule in the ember accent
   rather than the gold brand, so a caveat never reads as more brand chrome.
   -------------------------------------------------------------------------- */

.card-warn {
  border-left-width: 4px;
  border-left-color: var(--color-signal-500, #d6431a);
}

/* --------------------------------------------------------------------------
   Command blocks
   Install instructions are long single lines. They must scroll inside their own
   box rather than widening the page on a phone.
   -------------------------------------------------------------------------- */

.code-block {
  overflow-x: auto;
  border-radius: 0.75rem;
  border: 1px solid var(--surface-border);
  background-color: #100900;      /* deepest umber — dark in both themes, like a
                                     terminal. Stays below the dark page
                                     background (#150d00) so the block still
                                     reads as recessed rather than raised. */
  color: #f3e8d0;
  padding: 1rem 1.125rem;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.8125rem;
  line-height: 1.7;
  -webkit-overflow-scrolling: touch;
}

.dark .code-block { border-color: #43331d; }

/* Tighter variant for one-liners inside a card. A modifier class rather than
   Tailwind's important suffix, because .code-block lives in an unlayered
   stylesheet and would otherwise need `py-2.5!` to be overridden at all. */
.code-block-compact {
  padding: 0.625rem 0.875rem;
  font-size: 0.75rem;
}

.code-block code {
  display: block;
  white-space: pre;
}

/* Must come after `.code-block code` — same specificity, so source order is
   what decides. These are single commands inside a narrow card: wrapping reads
   better than a horizontal scrollbar the reader has to discover, and the
   hanging indent keeps the continuation clear of the prompt. */
.code-block-compact code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding-left: 1.1em;
  text-indent: -1.1em;
}

/* Shell prompts and comments, marked up with <span> in the template. */
.code-block .tok-prompt { color: #ffcc00; user-select: none; }
.code-block .tok-comment { color: #9a7c48; }

/* --------------------------------------------------------------------------
   Accessibility: respect reduced-motion preferences
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .card:hover { transform: none; }
}
