/* =============================================================
   utilities.css — minimal hand-rolled Tailwind-compatible utilities.
   Covers only the classes actually used in the templates, so we can
   drop the Tailwind CDN (~3 MB per page) without breaking layout.
   Tokens come from design-system.css.
   ============================================================= */

/* Display */
.flex         { display: flex; }
.inline-flex  { display: inline-flex; }
.grid         { display: grid; }
.block        { display: block; }
.inline-block { display: inline-block; }
.hidden       { display: none !important; }

/* Flex */
.flex-col      { flex-direction: column; }
.flex-wrap     { flex-wrap: wrap; }
.items-start   { align-items: flex-start; }
.items-center  { align-items: center; }
.items-end     { align-items: flex-end; }
.justify-start    { justify-content: flex-start; }
.justify-center   { justify-content: center; }
.justify-end      { justify-content: flex-end; }
.justify-between  { justify-content: space-between; }
.justify-around   { justify-content: space-around; }

/* Grid */
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Gap */
.gap-1 { gap: 4px; }
.gap-2 { gap: 8px; }
.gap-3 { gap: 12px; }
.gap-4 { gap: 16px; }
.gap-5 { gap: 20px; }
.gap-6 { gap: 24px; }
.gap-8 { gap: 32px; }

/* Spacing — margin */
.m-0 { margin: 0; }
.m-1 { margin: 4px; }
.m-2 { margin: 8px; }
.m-3 { margin: 12px; }
.m-4 { margin: 16px; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 4px; }
.mt-2 { margin-top: 8px; }
.mt-3 { margin-top: 12px; }
.mt-4 { margin-top: 16px; }
.mt-6 { margin-top: 24px; }
.mt-8 { margin-top: 32px; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 4px; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 12px; }
.mb-4 { margin-bottom: 16px; }
.mb-5 { margin-bottom: 20px; }
.mb-6 { margin-bottom: 24px; }
.mb-8 { margin-bottom: 32px; }
.ml-1 { margin-left: 4px; }
.ml-2 { margin-left: 8px; }
.ml-3 { margin-left: 12px; }
.mr-1 { margin-right: 4px; }
.mr-2 { margin-right: 8px; }
.mr-3 { margin-right: 12px; }
.mr-4 { margin-right: 16px; }
.mx-auto { margin-left: auto; margin-right: auto; }
.my-5 { margin-top: 20px; margin-bottom: 20px; }

/* RTL-aware logical margins — preferred over mr-*/ml-* for icon+text gaps. */
.me-1 { margin-inline-end: 4px; }
.me-2 { margin-inline-end: 8px; }
.me-3 { margin-inline-end: 12px; }
.ms-1 { margin-inline-start: 4px; }
.ms-2 { margin-inline-start: 8px; }
.ms-3 { margin-inline-start: 12px; }

/* RTL override: in this fa-ir/RTL app, treat existing .mr-* classes as
   margin-inline-end so legacy templates that use them for "gap between
   icon and text" work correctly without per-file edits. */
[dir="rtl"] .mr-1 { margin-right: 0; margin-inline-end: 4px; }
[dir="rtl"] .mr-2 { margin-right: 0; margin-inline-end: 8px; }
[dir="rtl"] .mr-3 { margin-right: 0; margin-inline-end: 12px; }
[dir="rtl"] .mr-4 { margin-right: 0; margin-inline-end: 16px; }

/* Spacing — padding */
.p-0 { padding: 0; }
.p-1 { padding: 4px; }
.p-2 { padding: 8px; }
.p-3 { padding: 12px; }
.p-4 { padding: 16px; }
.p-5 { padding: 20px; }
.p-6 { padding: 24px; }
.p-8 { padding: 32px; }
.pt-3 { padding-top: 12px; }
.pt-4 { padding-top: 16px; }
.pt-8 { padding-top: 32px; }
.pt-20 { padding-top: 80px; }
.pb-2 { padding-bottom: 8px; }
.pb-3 { padding-bottom: 12px; }
.pb-4 { padding-bottom: 16px; }
.pb-6 { padding-bottom: 24px; }
.px-2 { padding-left: 8px;  padding-right: 8px; }
.px-3 { padding-left: 12px; padding-right: 12px; }
.px-4 { padding-left: 16px; padding-right: 16px; }
.px-6 { padding-left: 24px; padding-right: 24px; }
.py-1 { padding-top: 4px;  padding-bottom: 4px; }
.py-2 { padding-top: 8px;  padding-bottom: 8px; }
.py-3 { padding-top: 12px; padding-bottom: 12px; }
.py-4 { padding-top: 16px; padding-bottom: 16px; }
.py-6 { padding-top: 24px; padding-bottom: 24px; }
.py-8 { padding-top: 32px; padding-bottom: 32px; }

/* Sizing */
.w-full    { width: 100%; }
.w-auto    { width: auto; }
/* Fractional widths used by the features modal et al. */
.w-1\/2    { width: 50%; }
.w-1\/3    { width: 33.333333%; }
.w-2\/3    { width: 66.666667%; }
.w-1\/4    { width: 25%; }
.w-3\/4    { width: 75%; }
.w-5\/6    { width: 83.333333%; }
.w-11\/12  { width: 91.666667%; }
.h-full    { height: 100%; }
.h-auto    { height: auto; }
.h-screen  { height: 100vh; }
.min-h-screen { min-height: 100vh; }
/* Fixed heights — Tailwind's spacing scale (4px base) */
.h-4   { height: 16px; }
.h-5   { height: 20px; }
.h-6   { height: 24px; }
.h-8   { height: 32px; }
.h-10  { height: 40px; }
.h-12  { height: 48px; }
.h-16  { height: 64px; }
.h-20  { height: 80px; }
.h-24  { height: 96px; }
.h-32  { height: 128px; }
.h-40  { height: 160px; }
.h-48  { height: 192px; }
.h-56  { height: 224px; }
.h-60  { height: 240px; }
.h-64  { height: 256px; }
.h-80  { height: 320px; }
.h-96  { height: 384px; }
.w-4   { width: 16px; }
.w-5   { width: 20px; }
.w-6   { width: 24px; }
.w-8   { width: 32px; }
.w-10  { width: 40px; }
.w-12  { width: 48px; }
.w-16  { width: 64px; }
.w-20  { width: 80px; }
.w-24  { width: 96px; }
.w-32  { width: 128px; }
.w-48  { width: 192px; }
.w-64  { width: 256px; }
.max-w-md  { max-width: 448px; }
.max-w-lg  { max-width: 512px; }
.max-w-xl  { max-width: 576px; }
.max-w-2xl { max-width: 672px; }
.max-w-3xl { max-width: 768px; }
.max-w-4xl { max-width: 896px; }
.max-w-5xl { max-width: 1024px; }
.max-w-6xl { max-width: 1152px; }
.max-w-7xl { max-width: 1280px; }

/* Position */
.relative { position: relative; }
.absolute { position: absolute; }
.fixed    { position: fixed; }
.sticky   { position: sticky; }

/* Overflow */
.overflow-hidden  { overflow: hidden; }
.overflow-y-auto  { overflow-y: auto; }
.overflow-x-auto  { overflow-x: auto; }

/* Borders */
.border    { border: 1px solid var(--ds-line); }
.border-0  { border: 0; }
.border-t  { border-top: 1px solid var(--ds-line); }
.border-b  { border-bottom: 1px solid var(--ds-line); }
.border-l  { border-left: 1px solid var(--ds-line); }
.border-r  { border-right: 1px solid var(--ds-line); }
.border-b-2 { border-bottom-width: 2px; }
.border-gray-200 { border-color: #E5E7EB; }
.border-gray-300 { border-color: #D1D5DB; }
.border-green-200 { border-color: #BBF7D0; }
.border-transparent { border-color: transparent; }

/* Radius */
.rounded     { border-radius: 6px; }
.rounded-sm  { border-radius: 4px; }
.rounded-md  { border-radius: 8px; }
.rounded-lg  { border-radius: 12px; }
.rounded-xl  { border-radius: 16px; }
.rounded-2xl { border-radius: 24px; }
.rounded-full { border-radius: 9999px; }

/* Text */
.text-center  { text-align: center; }
.text-right   { text-align: right; }
.text-left    { text-align: left; }
.text-xs   { font-size: 0.75rem;  line-height: 1rem; }
.text-sm   { font-size: 0.875rem; line-height: 1.25rem; }
.text-base { font-size: 1rem;     line-height: 1.5rem; }
.text-lg   { font-size: 1.125rem; line-height: 1.75rem; }
.text-xl   { font-size: 1.25rem;  line-height: 1.75rem; }
.text-2xl  { font-size: 1.5rem;   line-height: 2rem; }
.text-3xl  { font-size: 1.875rem; line-height: 2.25rem; }
.text-4xl  { font-size: 2.25rem;  line-height: 2.5rem; }
.text-5xl  { font-size: 3rem;     line-height: 1; }
.text-6xl  { font-size: 3.75rem;  line-height: 1; }

.font-medium   { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold     { font-weight: 700; }

/* Text colors — tap into design tokens where possible */
.text-white        { color: #fff; }
.text-black        { color: #000; }
.text-primary      { color: var(--ds-brand); }
.text-success      { color: var(--ds-success); }
.text-danger       { color: var(--ds-danger); }
.text-gray-400  { color: #9CA3AF; }
.text-gray-500  { color: #6B7280; }
.text-gray-600  { color: #4B5563; }
.text-gray-700  { color: #374151; }
.text-gray-800  { color: #1F2937; }
.text-green-500 { color: #10B981; }
.text-green-600 { color: #059669; }
.text-blue-600  { color: #2563EB; }
.text-blue-700  { color: #1D4ED8; }
.text-red-500   { color: #EF4444; }
.text-red-600   { color: #DC2626; }
.text-red-700   { color: #B91C1C; }
.text-yellow-500 { color: #EAB308; }
.text-orange-500 { color: #F97316; }
.text-inherit   { color: inherit; }

/* Decoration */
.no-underline { text-decoration: none; }
.underline    { text-decoration: underline; }

/* Line clamp — used in property card titles to keep them 2 lines tall.
   Tailwind ships with @tailwindcss/line-clamp; this is the manual version. */
.line-clamp-1, .line-clamp-2, .line-clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.line-clamp-1 { -webkit-line-clamp: 1; }
.line-clamp-2 { -webkit-line-clamp: 2; }
.line-clamp-3 { -webkit-line-clamp: 3; }

/* Grid column spans — used in empty-state cells that span the whole row. */
.col-span-1 { grid-column: span 1 / span 1; }
.col-span-2 { grid-column: span 2 / span 2; }
.col-span-3 { grid-column: span 3 / span 3; }
.col-span-4 { grid-column: span 4 / span 4; }
.col-span-full { grid-column: 1 / -1; }

/* Background colors — use Tailwind's --tw-bg-opacity pattern so
   `bg-black bg-opacity-60`, `bg-white bg-opacity-75` etc. work as expected
   (the `.bg-opacity-N` class only adjusts the variable). */
.bg-white       { --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); }
.bg-black       { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); }
.bg-transparent { background-color: transparent; }
.bg-primary     { --tw-bg-opacity: 1; background-color: rgb(0 166 147 / var(--tw-bg-opacity)); }
.bg-gray-50     { --tw-bg-opacity: 1; background-color: rgb(249 250 251 / var(--tw-bg-opacity)); }
.bg-gray-100    { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); }
.bg-gray-200    { --tw-bg-opacity: 1; background-color: rgb(229 231 235 / var(--tw-bg-opacity)); }
.bg-gray-600    { --tw-bg-opacity: 1; background-color: rgb(75 85 99 / var(--tw-bg-opacity)); }
.bg-green-50    { --tw-bg-opacity: 1; background-color: rgb(240 253 244 / var(--tw-bg-opacity)); }
.bg-green-500   { --tw-bg-opacity: 1; background-color: rgb(16 185 129 / var(--tw-bg-opacity)); }
.bg-green-600   { --tw-bg-opacity: 1; background-color: rgb(5 150 105 / var(--tw-bg-opacity)); }
.bg-blue-50     { --tw-bg-opacity: 1; background-color: rgb(239 246 255 / var(--tw-bg-opacity)); }

/* Background image positioning (used by JS-generated property cards) */
.bg-cover  { background-size: cover; }
.bg-contain { background-size: contain; }
.bg-center { background-position: center; }
.bg-no-repeat { background-repeat: no-repeat; }

/* Background opacity — only modulates the --tw-bg-opacity variable that
   the `.bg-{color}` classes above consume. So `bg-black bg-opacity-60`
   renders as 60% black, while `bg-white bg-opacity-75` is 75% white, etc. */
.bg-opacity-50  { --tw-bg-opacity: 0.5; }
.bg-opacity-60  { --tw-bg-opacity: 0.6; }
.bg-opacity-75  { --tw-bg-opacity: 0.75; }
.bg-opacity-100 { --tw-bg-opacity: 1; }

/* Shadows */
.shadow    { box-shadow: var(--ds-shadow-sm); }
.shadow-sm { box-shadow: var(--ds-shadow-xs); }
.shadow-md { box-shadow: var(--ds-shadow-md); }
.shadow-lg { box-shadow: var(--ds-shadow-lg); }
.shadow-xl { box-shadow: var(--ds-shadow-xl); }

/* Opacity */
.opacity-0   { opacity: 0; }
.opacity-50  { opacity: 0.5; }
.opacity-75  { opacity: 0.75; }
.opacity-80  { opacity: 0.8; }
.opacity-90  { opacity: 0.9; }
.opacity-100 { opacity: 1; }

/* Misc */
.cursor-pointer     { cursor: pointer; }
.pointer-events-none { pointer-events: none; }
.select-none        { user-select: none; }
.whitespace-nowrap  { white-space: nowrap; }
.truncate           { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.appearance-none    { appearance: none; -webkit-appearance: none; }

/* Transition / animation */
.transition-all    { transition: all var(--ds-normal); }
.transition-colors { transition: background-color var(--ds-fast), border-color var(--ds-fast), color var(--ds-fast), fill var(--ds-fast), stroke var(--ds-fast); }
.duration-200      { transition-duration: 200ms; }
.duration-300      { transition-duration: 300ms; }

/* Z-index */
.z-0   { z-index: 0; }
.z-10  { z-index: 10; }
.z-20  { z-index: 20; }
.z-50  { z-index: 50; }

/* Top/Right/Bottom/Left */
.inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
.top-0    { top: 0; }
.top-1    { top: 4px; }
.top-2    { top: 8px; }
.top-3    { top: 12px; }
.top-4    { top: 16px; }
.right-0  { right: 0; }
.right-1  { right: 4px; }
.right-2  { right: 8px; }
.right-3  { right: 12px; }
.right-4  { right: 16px; }
.bottom-0 { bottom: 0; }
.bottom-1 { bottom: 4px; }
.bottom-2 { bottom: 8px; }
.bottom-3 { bottom: 12px; }
.bottom-4 { bottom: 16px; }
.left-0   { left: 0; }
.left-1   { left: 4px; }
.left-2   { left: 8px; }
.left-3   { left: 12px; }
.left-4   { left: 16px; }

/* Accessibility */
.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;
}

/* Focus */
.focus\:outline-none:focus      { outline: none; }
.focus\:ring-2:focus            { box-shadow: 0 0 0 2px rgba(0, 166, 147, 0.4); }
.focus\:ring-primary-brand:focus { box-shadow: 0 0 0 3px rgba(0, 166, 147, 0.35); }

/* Hover */
.hover\:bg-green-50:hover    { background-color: #F0FDF4; }
.hover\:bg-gray-50:hover     { background-color: #F9FAFB; }
.hover\:bg-white:hover       { background-color: #fff; }
.hover\:text-gray-700:hover  { color: #374151; }
.hover\:text-white:hover     { color: #fff; }
.hover\:border-gray-300:hover { border-color: #D1D5DB; }
.hover\:opacity-80:hover     { opacity: 0.8; }
.hover\:no-underline:hover   { text-decoration: none; }

/* Responsive — sm (640px+).
   `display`/`flex-direction` use !important so they beat the unprefixed
   `.hidden` / `.flex-col` rules above (Tailwind does the same trick). */
@media (min-width: 640px) {
  .sm\:flex          { display: flex !important; }
  .sm\:flex-row      { flex-direction: row !important; }
  .sm\:flex-col      { flex-direction: column !important; }
  .sm\:grid          { display: grid !important; }
  .sm\:block         { display: block !important; }
  .sm\:hidden        { display: none !important; }
  .sm\:items-center  { align-items: center !important; }
  .sm\:items-start   { align-items: flex-start !important; }
  .sm\:text-left     { text-align: left !important; }
  .sm\:w-auto        { width: auto !important; }
  .sm\:grid-cols-2   { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .sm\:grid-cols-3   { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  .sm\:grid-cols-6   { grid-template-columns: repeat(6, minmax(0, 1fr)) !important; }
}

/* Responsive — md (768px+) */
@media (min-width: 768px) {
  .md\:flex          { display: flex !important; }
  .md\:flex-row      { flex-direction: row !important; }
  .md\:grid          { display: grid !important; }
  .md\:hidden        { display: none !important; }
  .md\:block         { display: block !important; }
  .md\:grid-cols-2   { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .md\:grid-cols-3   { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  .md\:grid-cols-4   { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
  .md\:items-center  { align-items: center !important; }
  .md\:w-auto        { width: auto !important; }
  .md\:col-span-2    { grid-column: span 2 / span 2 !important; }
  .md\:col-span-3    { grid-column: span 3 / span 3 !important; }
}

/* Responsive — lg (1024px+) */
@media (min-width: 1024px) {
  .lg\:flex          { display: flex !important; }
  .lg\:flex-row      { flex-direction: row !important; }
  .lg\:flex-col      { flex-direction: column !important; }
  .lg\:grid          { display: grid !important; }
  .lg\:hidden        { display: none !important; }
  .lg\:block         { display: block !important; }
  .lg\:grid-cols-2   { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .lg\:grid-cols-3   { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  .lg\:grid-cols-4   { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
  .lg\:w-1\/3        { width: 33.333333% !important; }
  .lg\:w-2\/3        { width: 66.666667% !important; }
  .lg\:w-1\/2        { width: 50% !important; }
  .lg\:items-center  { align-items: center !important; }
  .lg\:col-span-3    { grid-column: span 3 / span 3 !important; }
  .lg\:col-span-4    { grid-column: span 4 / span 4 !important; }
}

/* `space-y-*` — vertical rhythm between flex/block siblings (Tailwind shape) */
.space-y-1 > * + * { margin-top: 4px; }
.space-y-2 > * + * { margin-top: 8px; }
.space-y-3 > * + * { margin-top: 12px; }
.space-y-4 > * + * { margin-top: 16px; }
.space-y-6 > * + * { margin-top: 24px; }
.space-y-8 > * + * { margin-top: 32px; }
.space-x-2 > * + * { margin-inline-start: 8px; }
.space-x-3 > * + * { margin-inline-start: 12px; }
.space-x-4 > * + * { margin-inline-start: 16px; }

/* Hover variants used by feature/list-desktop templates */
.hover\:bg-gray-200:hover    { background-color: #E5E7EB; }
.hover\:bg-green-50:hover    { background-color: #F0FDF4; }
.hover\:border-green-500:hover { border-color: var(--ds-success); }
.hover\:text-green-700:hover { color: #047857; }
.hover\:text-gray-900:hover  { color: #111827; }

/* Focus variants */
.focus\:ring-green-500:focus { box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.35); }
.focus\:border-green-500:focus { border-color: var(--ds-success); }
