@import "tailwindcss";

/* Self-hosted fonts — served via Propshaft (URLs rewritten to digested paths at compile time) */

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/jetbrains-mono-400-849c32ea.woff2") format("woff2");
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/jetbrains-mono-600-eee40bb0.woff2") format("woff2");
}

@font-face {
  font-family: "Saira Condensed";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/saira-condensed-400-ab14c79b.woff2") format("woff2");
}

@font-face {
  font-family: "Saira Condensed";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/saira-condensed-500-ed17f249.woff2") format("woff2");
}

@font-face {
  font-family: "Saira Condensed";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/saira-condensed-600-5baaa405.woff2") format("woff2");
}

@font-face {
  font-family: "Saira Condensed";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/saira-condensed-700-11404b59.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/assets/space-grotesk-300-2876ead4.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/space-grotesk-400-b217bce7.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/space-grotesk-500-4b7aea1d.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/space-grotesk-600-ab3ffa9f.woff2") format("woff2");
}

@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/space-grotesk-700-36c6c9a5.woff2") format("woff2");
}

@theme {
  /* Background layers */
  --color-bg: #0A0C0F;
  --color-surface: #14181D;
  --color-surface-raised: #1C2128;
  --color-line: #262C34;

  /* Brand */
  --color-primary: #E2001A;

  /* Text */
  --color-text: #F2F4F7;
  --color-muted: #9AA4B2;

  /* Data-semantic accents */
  --color-accent-purple: #A855F7;
  --color-accent-green: #22C55E;
  --color-accent-amber: #F59E0B;
  --color-accent-blue: #2F8FFF;

  /* Diagnostic error colours — resolved by JS via getComputedStyle so canvas/WebGL
     can read the same tokens without hardcoding hex in JavaScript. */
  --color-error-collision: #ff3b30;
  /* Severity ladder: floating (amber) → off-platform (orange) → collision (red) */
  --color-warn-off-platform: #F97316;

  /* Track canvas */
  --color-asphalt: #141414;

  /* Typography */
  --font-display: "Saira Condensed", system-ui, sans-serif;
  --font-sans: "Space Grotesk", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
}

@layer base {
  /* Tailwind v4 dropped the default `cursor: pointer` v3 applied to buttons —
     restore pointer/not-allowed cursors on native interactive elements
     app-wide (planner-specific drag cursors stay in .is-manipulating below). */
  button,
  [role="button"],
  summary,
  label[for],
  select,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="checkbox"],
  input[type="radio"],
  input[type="file"] {
    cursor: pointer;
  }

  button:disabled,
  [role="button"][aria-disabled="true"],
  input:disabled,
  select:disabled,
  [aria-disabled="true"] {
    cursor: not-allowed;
  }
}

/* Themed scrollbars — token-driven so they adapt automatically if light-mode tokens
   are ever introduced. Firefox uses scrollbar-width/color; WebKit uses the pseudo-
   element API. Goal: a thin, rounded, low-contrast thumb that recedes into dark
   surfaces but is still a visible affordance, brightening on hover. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-line) transparent;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--color-line);
  border-radius: 9999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--color-muted);
  background-clip: padding-box;
}

/* Catalog thumbnail footprint classes — consumed by catalog_piece_controller.js.
   Using hand-written CSS so token-referenced fills compile regardless of whether
   the class names appear in scanned template files (Tailwind v4 JIT cannot see
   dynamically assigned class strings set from JavaScript). */
.footprint-fill {
  fill: var(--color-asphalt);
}

.footprint-slot {
  stroke: var(--color-line);
  stroke-width: 3;
}

.footprint-marking {
  stroke: var(--color-text);
  stroke-width: 1.5;
}

.footprint-marking--dashed {
  stroke-dasharray: 12 8;
}

.footprint-apron {
  fill: var(--color-muted);
}

/* .footprint-curb fill is set inline via url(#pattern-id) from the controller. */

/* Rail tab triggers — aria-selected drives the active underline so the
   controller only needs to set the attribute, not juggle classes. */
.tab-trigger {
  @apply border-b-2 border-transparent font-mono text-[10px] tracking-[0.2em] uppercase transition text-muted;
}
.tab-trigger:hover {
  @apply text-text;
}
.tab-trigger[aria-selected="true"] {
  @apply border-primary text-text;
}

/* Manipulation-gesture affordances — .is-manipulating and .is-dragging are
   toggled dynamically by planner_controller.js's #setManipulating /
   #setPaletteDragAffordance, so (like .footprint-fill above) they're
   hand-written here rather than as scanned Tailwind utility classes — the
   JIT never sees a class string that only ever appears in a
   classList.toggle() call. */

/* While ANY manipulation gesture is in flight — palette drag, piece/layout
   move, piece/layout/scenery rotate, scenery move, or canvas pan — the
   pointer is captured (by the canvas, or by the source button for a
   palette drag) for the whole gesture, so whatever element it happens to
   be hovering can still show its own resting cursor (pointer/grab/move)
   unless we override it. Force the grabbing cursor everywhere under the
   planner root so every gesture reads clearly regardless of what's
   actually under the (captured) pointer. */
.is-manipulating,
.is-manipulating * {
  cursor: grabbing !important;
}

/* The palette item currently being dragged — "you're carrying this piece". */
.is-dragging {
  @apply ring-2 ring-primary opacity-60;
}

/* Sinks a disabled assembly action item (hairpin, pit lane) to the bottom of
   the palette grid, so an ineligible multi-piece item never leads ahead of a
   placeable one — default grid items sit at order: 0. */
.palette-item-sunk {
  order: 1;
}

/* Lexxy editor — map to Telemetry Dark tokens.
   Dark is the default; no light-mode split needed for this app. */
lexxy-editor {
  --lexxy-color-canvas: var(--color-surface-raised);
  --lexxy-color-ink: var(--color-text);
  --lexxy-color-ink-medium: var(--color-muted);
  --lexxy-color-ink-light: var(--color-line);
  --lexxy-color-ink-lighter: var(--color-line);
  --lexxy-color-ink-lightest: var(--color-surface);
  --lexxy-color-ink-inverted: var(--color-surface);
  --lexxy-color-text: var(--color-text);
  --lexxy-color-text-subtle: var(--color-muted);
  --lexxy-font-base: var(--font-sans);

  border-color: var(--color-line);
  border-radius: 0.375rem;
}

/* Lexxy rendered content — wraps Action Text output via _content.html.erb */
.lexxy-content {
  color: var(--color-text);
  line-height: 1.625;
}

/* Blueprint grid — the planner canvas background.
   Faint 1px lines on a ~28px grid over the deep canvas surface.
   Hand-written so the class name is always present for the JIT scanner. */
.blueprint-grid {
  background-color: #0b0e12;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 28px 28px;
}
