/*
 * v2 unified stylesheet.
 *
 * Single source of truth for v2 design tokens + responsive behavior.
 * Consolidates mobile CSS from the 4 places v1 scattered it:
 *   - public/css/layout.css:442+
 *   - public/css/design-system.css (bottom)
 *   - PageShell.tsx (inline)
 *   - PropertyClient.tsx (inline ~line 780)
 *
 * Only lives in ONE place from here forward.
 */

/* ------------------------------------------------------------------
   Design tokens
   ------------------------------------------------------------------ */

:root {
  /* Surface — v2 light defaults (flipped to dark inside .v2-main below) */
  --color-bg:             oklch(98% 0.005 248);
  --color-bg-subtle:      oklch(96% 0.008 248);
  --color-surface:        oklch(100% 0 0);
  --color-surface-subtle: oklch(96% 0.008 248);
  --color-surface-raised: oklch(100% 0 0);

  /* Foreground */
  --color-fg:           oklch(18% 0.02 248);
  --color-fg-subtle:    oklch(36% 0.02 248);
  --color-muted:        oklch(50% 0.02 248);
  --color-muted-strong: oklch(38% 0.02 248);

  /* Border */
  --color-border:        oklch(0% 0 0 / 0.08);
  --color-border-strong: oklch(0% 0 0 / 0.14);

  /* Brand + semantic — amber is the only accent */
  --color-brand:       oklch(66% 0.15 42);     /* amber-deep for light-mode contrast */
  --color-brand-hover: oklch(60% 0.16 40);
  --color-link:        oklch(66% 0.15 42);

  --color-success:    oklch(55% 0.17 148);
  --color-success-fg: oklch(35% 0.15 148);
  --color-success-bg: oklch(70% 0.17 148 / 0.18);

  --color-warning:    oklch(66% 0.15 42);     /* merged with amber */
  --color-warning-fg: oklch(40% 0.13 40);
  --color-warning-bg: oklch(76% 0.14 58 / 0.2);

  --color-danger:    oklch(55% 0.22 25);
  --color-danger-fg: oklch(40% 0.18 25);
  --color-danger-bg: oklch(65% 0.22 25 / 0.18);

  /* Typography — inherit from variables.css so the A/A/A font-size toggle
     (compact/default/large via [data-fontsize]) actually affects v2 panels.
     Previously this :root block hardcoded px values and — because v2.css loads
     AFTER variables.css — won the cascade, defeating the toggle everywhere
     under v2.
     Only --text-4xl is defined here because variables.css doesn't ship one. */
  --text-4xl: 2.75rem;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;

  /* Radius — zeroed per user sharp-corners preference (see memory
     preference_sharp_corners.md). --radius-full stays for circles. */
  --radius-sm: 0;
  --radius-md: 0;
  --radius-lg: 0;
  --radius-xl: 0;
  --radius-full: 9999px;

  /* Shadow */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08);
  --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12);

  /* Layout */
  --container-max: 1280px;
  --tab-bar-height: 48px;
  --header-height: 56px;
  --sidebar-width: 240px;
}

/* ------------------------------------------------------------------
   Dark mode (opt-in via [data-theme=dark])
   ------------------------------------------------------------------ */

[data-theme='dark'] {
  --color-bg:             oklch(8%  0.02  248);
  --color-bg-subtle:      oklch(11% 0.023 248);
  --color-surface:        oklch(11% 0.023 248);
  --color-surface-subtle: oklch(14% 0.026 248);
  --color-surface-raised: oklch(18% 0.025 248);

  --color-fg:           oklch(96% 0.01 248);
  --color-fg-subtle:    oklch(80% 0.02 248);
  --color-muted:        oklch(72% 0.02 248);
  --color-muted-strong: oklch(50% 0.02 248);

  --color-border:        oklch(26% 0.02 248 / 0.55);
  --color-border-strong: oklch(34% 0.02 248 / 0.7);

  --color-brand:       oklch(76% 0.14 58);
  --color-brand-hover: oklch(80% 0.1  64);
  --color-link:        oklch(76% 0.14 58);

  --color-warning-bg: oklch(22% 0.06 58 / 0.5);
  --color-warning-fg: oklch(82% 0.12 62);

  --shadow-sm: 0 1px 2px oklch(2% 0.015 248 / 0.4);
  --shadow-md: 0 4px 12px oklch(2% 0.015 248 / 0.35);
  --shadow-lg: 0 12px 32px oklch(2% 0.015 248 / 0.45);
}

/* ------------------------------------------------------------------
   Responsive breakpoints
   ------------------------------------------------------------------ */

/* Tablet: <= 768px */
@media (max-width: 768px) {
  :root {
    --space-4: 12px;           /* tighter padding on small screens */
    --space-6: 16px;
    --space-8: 24px;
    /* --text-base deliberately not overridden here — variables.css owns the
       type scale and responds to data-fontsize toggle. Overriding --text-base
       at :root scope wins over [data-fontsize="X"] selectors and breaks the
       toggle on small screens. */
  }
}

/* Phone: <= 480px */
@media (max-width: 480px) {
  :root {
    --space-3: 10px;
    --space-4: 10px;           /* CLAUDE.md: 12px single-layer padding */
    --space-6: 14px;
    --sidebar-width: 0;        /* sidebar collapses on phone */
  }
}

/* ------------------------------------------------------------------
   Layout primitives — used by app-v2 route groups
   ------------------------------------------------------------------ */

.v2-main {
  min-height: 100vh;
  /* When rendered inside the main app layout (which paints its own dark
     background), let that background show through. When rendered on /beta
     (which has no dark shell), fall back to the v2 theme's own --color-bg. */
  background: transparent;
  color: var(--color-fg);
  /* Landing-page body font. The previous 'DM Sans' fallback was dead weight —
     not loaded anywhere, so browsers fell through to system-ui. Inter matches
     the landing page and is already loaded globally in app/layout.tsx. */
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  /* `clip` (not `hidden`) keeps horizontal containment without creating a
     scroll container — so `position: sticky` descendants (the property
     header + tab rail) pin to the viewport instead of to .v2-main. */
  overflow-x: clip;
}

/* When .v2-main is rendered inside the AuthedShell (app shell), its
   parent <main class="main"> already enforces min-height: 100svh and
   the AppFooter is positioned via margin-top:auto in that flex column.
   Letting .v2-main also claim min-height:100vh stacks the constraints —
   total page becomes 100vh + chrome (sticky header + tabs + bottom
   footer + .main's own padding-top:48px on mobile) = ~970px on a
   874px viewport → scroll where there should be none. Short tabs
   (vacant land Use & Development, Finances with no history, etc.)
   exposed this. Override to auto so .v2-main sizes to content and
   the outer .main fills the viewport via its own min-height. */
.page-body-full .v2-main {
  min-height: auto;
}

/* Standalone /beta pages need their own block padding (page-body-full isn't
   the parent there). Inside the app shell, page-body-full already supplies
   24px on every side so we don't double-pad vertically. */
body:not(.app-shell-dark) .v2-main {
  background: var(--color-bg);
  padding-block: var(--space-6);
}

/* When inside main app (which is dark by default), flip v2 to dark mode
   tokens so cards match the shell. This is load-bearing: without it users
   see white cards on a dark sidebar — the jarring mismatch reported
   in the screenshots. Explicit light-theme override still works via
   data-theme='light' on <html>. */
@media (prefers-color-scheme: no-preference) {}  /* reserved */
html:not([data-theme='light']) .v2-main,
html:not([data-theme='light']) .v2-main * {
  /* no-op selector keeps dark as the default for in-app v2 rendering */
}

/* Per-theme .v2-main overrides. The `.v2-main` selector has higher
   specificity than the bare `[data-theme='dark']` block at the top, so we
   need explicit per-theme rules here or dark-mode would never flip v2
   pages. Each block mirrors its matching theme palette in variables.css. */
html[data-theme='default'] .v2-main {
  --color-bg:             oklch(12% 0.025 248);
  --color-bg-subtle:      oklch(15% 0.027 248);
  --color-surface:        oklch(15% 0.027 248);
  --color-surface-subtle: oklch(18% 0.025 248);   /* signature dark green */
  --color-surface-raised: oklch(22% 0.028 248);
  --color-fg:           oklch(96% 0.01 248);
  --color-fg-subtle:    oklch(80% 0.02 248);
  --color-muted:        oklch(72% 0.02 248);
  --color-muted-strong: oklch(50% 0.02 248);
  --color-border:        oklch(30% 0.022 248 / 0.55);
  --color-border-strong: oklch(36% 0.022 248 / 0.7);
  --color-brand:       oklch(76% 0.14 58);
  --color-brand-hover: oklch(80% 0.1  64);
  --color-link:        oklch(76% 0.14 58);
  --color-warning-bg: oklch(22% 0.06 58 / 0.5);
  --color-warning-fg: oklch(82% 0.12 62);
}

html[data-theme='dark'] .v2-main {
  --color-bg:             oklch(8%  0.02  248);
  --color-bg-subtle:      oklch(11% 0.023 248);
  --color-surface:        oklch(11% 0.023 248);
  --color-surface-subtle: oklch(14% 0.026 248);
  --color-surface-raised: oklch(18% 0.025 248);
  --color-fg:           oklch(96% 0.01 248);
  --color-fg-subtle:    oklch(80% 0.02 248);
  --color-muted:        oklch(72% 0.02 248);
  --color-muted-strong: oklch(50% 0.02 248);
  --color-border:        oklch(26% 0.02 248 / 0.55);
  --color-border-strong: oklch(34% 0.02 248 / 0.7);
  --color-brand:       oklch(76% 0.14 58);
  --color-brand-hover: oklch(80% 0.1  64);
  --color-link:        oklch(76% 0.14 58);
  --color-warning-bg: oklch(22% 0.06 58 / 0.5);
  --color-warning-fg: oklch(82% 0.12 62);
}

.v2-container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-6);
}

/* When rendered inside the main app shell, .page-body-full already gives
   us 24px horizontal padding. The v2-container's own padding-inline doubles
   that into a noticeable inset. Strip it so content flushes to the same
   edge as the rest of the app. Standalone /beta routes still get the
   container padding because they don't sit inside .page-body-full. */
.page-body-full .v2-container {
  padding-inline: 0;
}

@media (max-width: 768px) {
  .v2-container {
    padding-inline: var(--space-4);
  }
  /* Mobile app-shell fix 2026-04-22: .page-body-full drops its own
     horizontal padding to 0 on mobile (see layout.css:686), and the
     v2-container override above zeroed our padding too — result: KV
     labels and values were clipping against the viewport edge (Image
     #19 Use & Development tab). Restore mobile padding INSIDE
     .page-body-full so v2 content doesn't kiss the edge. */
  .page-body-full .v2-container {
    padding-inline: 12px;
  }
  /* KVTable grid: lower minmax floor ONLY on mobile so narrow portrait
     (~336px of content after padding) fits 2-up instead of 1-up with
     half the row blank on the right. Desktop keeps its 200px floor
     (set inline in KVTable.tsx) so label-heavy stats don't crowd into
     5-col density on the 860px report. */
  .kv-table-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr)) !important;
  }
}

/* Grid helper — always minmax(min(Xpx, 100%), 1fr) per CLAUDE.md rule */
.v2-grid {
  display: grid;
  gap: var(--space-4);
}

.v2-grid-auto-200 {
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}

.v2-grid-auto-280 {
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}

.v2-grid-auto-360 {
  grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
}

/* ------------------------------------------------------------------
   Utilities
   ------------------------------------------------------------------ */

.v2-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.v2-focus-ring:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Horizontal scroll regions (tab rails, chip rows).
   Declare both axes explicitly so the CSS quirk "overflow-x: auto makes
   overflow-y compute to auto" doesn't render stray vertical scrollbars. */
.v2-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;     /* iOS inertial scroll */
  overscroll-behavior-x: contain;         /* don't bleed scroll to parent/page */
  scrollbar-gutter: stable;
}

/* Desktop: thin, polished scrollbar only on pointer devices */
@media (hover: hover) and (pointer: fine) {
  .v2-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--color-border-strong) transparent;
  }
  .v2-scroll::-webkit-scrollbar {
    height: 6px;
    width: 0;                             /* kill vertical rail explicitly */
  }
  .v2-scroll::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: var(--radius-full);
  }
  .v2-scroll::-webkit-scrollbar-track {
    background: transparent;
  }
}

/* Mobile / touch: hide the scrollbar entirely — swipe is the gesture.
   Keeps the visual clean; users scroll horizontally via touch. */
@media (hover: none) and (pointer: coarse) {
  .v2-scroll {
    scrollbar-width: none;
  }
  .v2-scroll::-webkit-scrollbar {
    display: none;
  }
}

/* ------------------------------------------------------------------
   KVTable row responsive behavior

   Rows are `label │ value` on desktop. On narrow screens (<480px),
   long property values (full owner names, legal addresses) push the
   right-aligned value off the row. Stacking label-above-value keeps
   every line legible without horizontal scroll.

   The selector targets children of the v2-kv-row class used by the
   KVTable primitive (see lib/v2/ui/primitives/KVTable.tsx).
   ------------------------------------------------------------------ */

@media (max-width: 480px) {
  .v2-kv-row {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 2px !important;
  }
  .v2-kv-row > span:first-child { min-width: 0 !important; }
  .v2-kv-row > span:nth-child(2) {
    text-align: left !important;
    width: 100%;
  }
}

/* KVTable row hover (desktop only — no hover on touch).
   Gives interactive rows (onClick/href) a subtle affordance consistent
   with the ActionBar and Section styling. */
@media (hover: hover) and (pointer: fine) {
  button.v2-kv-row:hover,
  a.v2-kv-row:hover {
    background: var(--bg-hover, var(--color-surface-subtle));
  }
}
