@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    /* Inter is self-hosted by tailwindcss-rails as "Inter var" (the inter-font stylesheet, font-display: swap) */
    --font-sans: 'Inter var', Inter, ui-sans-serif, system-ui, sans-serif;
    /* the sticky points bar's height, kept current by points_bar_controller; sticky table headers sit under it */
    --points-bar-h: 0px;
    
    --background: 210 20% 97%;
    --foreground: 210 25% 15%;
    
    --card: 0 0% 100%;
    --card-foreground: 210 25% 15%;
    
    --popover: 0 0% 100%;
    --popover-foreground: 210 25% 15%;
    
    --primary: 210 80% 25%;
    --primary-foreground: 210 20% 98%;
    
    --secondary: 210 15% 90%;
    --secondary-foreground: 210 25% 15%;
    
    --muted: 210 15% 94%;
    --muted-foreground: 210 50% 30%;
    
    --accent: 210 30% 85%;
    --accent-foreground: 210 25% 15%;
    
    --destructive: 0 70% 60%;
    --destructive-foreground: 210 20% 98%;
    
    --border: 210 15% 86%;
    --input: 210 15% 86%;
    --ring: 210 80% 25%;
    
    --radius: 0.25rem;

    /* Chart series (Chart.js / Chartkick read these through app/javascript/theme_colors.js).
       Series 1 is the primary; legacy hex series colours in templates are mapped onto these. */
    --chart-1: 210 80% 25%;
    --chart-2: 346 68% 36%;
    --chart-3: 142 64% 24%;
    --chart-4: 26 90% 37%;
    --chart-5: 272 67% 39%;
  }
}

@layer base {
  * {
    @apply border-border;
  }

  /* Two faces. JetBrains Mono is the site face: headings, taglines, labels, numbers, tables,
     nav, one-line copy. Inter is opt-in for long-form reading only: .prose blocks and anything
     given font-sans (multi-sentence explanatory paragraphs). A tagline under a heading stays mono. */
  html, body {
    font-family: var(--font-mono);
  }
  html {
    scroll-padding-top: calc(var(--points-bar-h) + 1rem);
  }

  body {
    @apply bg-background text-foreground;
    margin: 0;
    min-height: 100vh;
    font-feature-settings: "ss01", "ss02", "cv01", "cv02";
  }

  .prose {
    font-family: var(--font-sans);
  }
  /* headings, data and controls stay mono even inside prose */
  :where(h1, h2, h3, h4, h5, h6, table, code, kbd, pre, samp, label, button, input, select, textarea, .label, [class*="tabular-nums"]) {
    font-family: var(--font-mono);
  }

  /* No double-tap zoom or 300 ms tap delay on anything tappable. Pinch-zoom stays: the viewport
     never sets maximum-scale. */
  html, body, a, button, input, select, textarea, label, summary,
  [role="button"], [role="radio"], [role="tab"], [role="switch"], [data-action] {
    touch-action: manipulation;
  }
}

/* ---------------------------------------------------------------------------------------------
   Draw-odds shared pieces: points bar slider, odds badge, data tables. */
@layer components {
  /* Points slider: 44px hit area, 32px thumb, track coloured by --track when a page sets it.
     touch-action: none (not pan-y): the owner's phone test turned pan-y drags into scrolls. */
  input[type="range"].pts-range { -webkit-appearance: none; appearance: none; height: 44px; background: transparent; cursor: pointer; touch-action: none; }
  input[type="range"].pts-range:focus { outline: none; }
  input[type="range"].pts-range::-webkit-slider-runnable-track { height: 10px; border-radius: 9999px; background: var(--track, hsl(var(--secondary))); border: 1px solid hsl(var(--border)); }
  input[type="range"].pts-range::-moz-range-track { height: 10px; border-radius: 9999px; background: var(--track, hsl(var(--secondary))); border: 1px solid hsl(var(--border)); }
  input[type="range"].pts-range::-webkit-slider-thumb { -webkit-appearance: none; width: 32px; height: 32px; margin-top: -12px; border-radius: 9999px; background: hsl(var(--primary)); border: 3px solid #fff; box-shadow: 0 1px 4px rgb(0 0 0 / .35); }
  input[type="range"].pts-range::-moz-range-thumb { width: 26px; height: 26px; border-radius: 9999px; background: hsl(var(--primary)); border: 3px solid #fff; box-shadow: 0 1px 4px rgb(0 0 0 / .35); }
  input[type="range"].pts-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px hsl(var(--ring) / .35); }
  input[type="range"].pts-range:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px hsl(var(--ring) / .35); }

  /* A second slider laid invisibly over a band bar (the ladder) so the bar itself drags. Put it in
     a `relative` wrapper; it binds to points-bar as an extra `range` target. */
  input[type="range"].band-range { -webkit-appearance: none; appearance: none; position: absolute; left: 0; top: -14px; width: 100%; height: 44px; margin: 0; background: transparent; opacity: 0; cursor: pointer; touch-action: none; }
  input[type="range"].band-range::-webkit-slider-thumb { -webkit-appearance: none; width: 24px; height: 44px; }
  input[type="range"].band-range::-moz-range-thumb { width: 24px; height: 44px; border: 0; }

  /* Tables. Sentence-case muted header, 44px rows; numbers and dates never wrap, the label
     column absorbs the wrapping. Phones never swipe a table sideways: drop columns
     (hidden md:table-cell) or stack the table (.data-table-stack). */
  .data-table-wrap { @apply overflow-x-auto; }
  .data-table { @apply w-full border-collapse text-base; }
  .data-table thead th { @apply h-11 bg-muted px-3 text-left align-middle text-sm font-medium text-muted-foreground whitespace-nowrap; }
  .data-table tbody tr { @apply h-11 border-t border-border; }
  .data-table tbody td, .data-table tbody th { @apply px-3 py-2 align-middle; }
  .data-table .num { @apply text-right tabular-nums whitespace-nowrap; }
  .data-table .date { @apply tabular-nums whitespace-nowrap; }
  .data-table .label-cell { @apply w-full min-w-0; }
  .data-table tr.is-you { @apply bg-primary/5 font-semibold; }
  /* Header sticks under the points bar. Sticky cannot escape an overflow container, so a sticky
     table goes without .data-table-wrap. */
  .data-table-sticky thead th { @apply sticky z-10; top: var(--points-bar-h); }
  /* Below md each row becomes a card: header hidden, each cell labelled by its data-label. */
  @media (max-width: 767.98px) {
    .data-table-stack thead { @apply sr-only; }
    .data-table-stack, .data-table-stack tbody, .data-table-stack tr, .data-table-stack td, .data-table-stack tbody th { display: block; }
    .data-table-stack tbody tr { @apply h-auto py-2; }
    .data-table-stack tbody td, .data-table-stack tbody th { @apply flex items-baseline justify-end gap-x-2 px-3 py-1 text-right; }
    .data-table-stack tbody td[data-label]::before { content: attr(data-label); @apply mr-auto pr-4 text-left text-sm font-normal text-muted-foreground; }
    .data-table-stack .label-cell { width: auto; }
  }
}

/* ---------------------------------------------------------------------------------------------
   Site-wide components (docs/site-audit-2026-10-15/style.md §8). One heading scale, one button
   set, muted metadata, the card. Use these instead of hand-building the same thing per page. */
@layer components {
  /* Headings: .h1 for every page title, .h1-display for the homepage and hubs only. */
  .h1 { @apply text-3xl md:text-4xl font-bold tracking-tight; }
  .h1-display { @apply text-3xl md:text-5xl font-extrabold tracking-tight; }
  .h2 { @apply text-2xl font-bold; }
  .h3 { @apply text-lg font-semibold; }

  /* Buttons. No font size: they take the surrounding size (16px body); add text-sm where a
     compact control is wanted. */
  .btn-primary {
    @apply inline-flex items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 font-semibold text-primary-foreground cursor-pointer
           transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background
           disabled:pointer-events-none disabled:opacity-50;
  }
  .btn-secondary {
    @apply inline-flex items-center justify-center gap-2 rounded-lg border border-border bg-card px-4 py-2 font-semibold text-foreground cursor-pointer
           transition-colors hover:border-primary hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background
           disabled:pointer-events-none disabled:opacity-50;
  }
  .btn-link {
    @apply inline-flex items-center gap-1 rounded font-semibold text-primary underline-offset-2 hover:underline
           focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background;
  }
  .btn-ghost {
    @apply inline-flex items-center justify-center px-4 py-2 text-sm font-medium ring-offset-background transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
  }

  /* Muted metadata (dates, counts, "Last verified …"): a neutral grey, so the only blue-ish
     text on a page is a link or the primary colour. */
  .meta { @apply text-sm text-foreground/70; }

  .card {
    @apply border bg-card text-card-foreground shadow-sm;
  }
}

/* One inline-link style for body copy: links written without classes (admin HTML, prose) are
   the primary colour and underline on hover. :where() keeps it at zero specificity, so any
   utility class on a link still wins. */
@layer base {
  :where(.prose, main p, main li, main dd, main td) :where(a:not([class])) {
    @apply text-primary underline-offset-2 hover:underline;
  }
}

/* Animated ellipsis */
@keyframes ellipsis {
  0% { content: "Search Caliber"; }
  25% { content: "Search Caliber."; }
  50% { content: "Search Caliber.."; }
  75% { content: "Search Caliber..."; }
  100% { content: "Search Caliber"; }
}

.search-input::placeholder {
  animation: ellipsis 2s steps(1) infinite;
}

/* Subtle scanlines effect */
.scanlines {
  position: relative;
}

.scanlines::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  background: repeating-linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.02) 0,
    rgba(0, 0, 0, 0.02) 1px,
    transparent 1px,
    transparent 2px
  );
  pointer-events: none;
}
/* ---------------------------------------------------------------------------------------------
   Zeroing sections (spec §2). Every zero panel is in the HTML on load. Without JS everything is
   visible and stacked; the zero-toggle controller adds .js-enabled and collapses the inactive
   panels with display:none. No `hidden` attribute, no aria-hidden on indexable content. */
@layer components {
  .zero-panel { display: block; }
  .js-enabled .zero-panel { display: none; }
  .js-enabled .zero-panel.is-active { display: block; }

  .zero-tab[aria-selected="true"] { @apply border-primary bg-primary text-primary-foreground; }

  /* Drop-unit columns: all three are rendered; the table's class decides which is shown. */
  .zero-table.drop-in  .col-moa, .zero-table.drop-in  .col-mil,
  .zero-table.drop-moa .col-in,  .zero-table.drop-moa .col-mil,
  .zero-table.drop-mil .col-in,  .zero-table.drop-mil .col-moa { display: none; }
  .drop-unit[aria-pressed="true"] { @apply border-primary bg-primary text-primary-foreground; }
}

/* ---------------------------------------------------------------------------------------------
   Draw-odds hub map (DrawOdds::HubMap). The state abbreviation and day-count labels are SVG text
   that scales with the map; under md they would shrink below the 14px floor, so they are hidden
   and the tooltip / aria-label carries the figure instead. Hovered states lift slightly. */
.hub-map-label { display: none; }
@media (min-width: 768px) { .hub-map-label { display: inline; } }
.hub-map a:hover path, .hub-map a:focus path { opacity: 0.85; }

/* ---------------------------------------------------------------------------------------------
   Species page hunt table (app/views/draw_odds/_species_table.html.erb): eight columns beside the
   map at xl, so cells sit closer than the shared .data-table's px-3. */
@layer components {
  .species-table thead th, .species-table tbody td { padding-left: 0.5rem; padding-right: 0.5rem; }
  .species-table thead th:first-child, .species-table tbody td:first-child { padding-left: 0.75rem; }
  .species-table thead th:last-child, .species-table tbody td:last-child { padding-right: 0.75rem; }
}

/* ---------------------------------------------------------------------------------------------
   Hunt-code and unit pages (draw_odds/hunt_code, unit): collapsed sections use a ▸ that turns
   when open, with no browser marker; anchors land below the sticky points bar. */
.draw-odds-details details > summary { list-style: none; cursor: pointer; touch-action: manipulation; }
.draw-odds-details details > summary::-webkit-details-marker { display: none; }
.draw-odds-details details[open] > summary .chev { transform: rotate(90deg); }
html:has(.draw-odds-details) { scroll-padding-top: calc(var(--points-bar-h, 0px) + 1rem); }
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *


 */

/* Hunt-unit topographic map (Leaflet, loaded on demand) */
.topo-unit-label {
  background: transparent;
  border: 0;
  box-shadow: none;
  color: hsl(var(--muted-foreground));
  font-size: 14px;
  font-weight: 600;
  text-shadow: 0 0 3px hsl(var(--background)), 0 0 3px hsl(var(--background));
}
.topo-unit-label--active { color: hsl(var(--primary)); font-size: 15px; }
.leaflet-container { border-radius: var(--radius); font: inherit; }
