/*
 * Custom semantic color utilities
 *
 * Metronic's precompiled styles.css only ships utility classes for
 * --primary and --destructive. This file adds the missing aliases for
 * danger / success / warning / info so the rest of the views work.
 *
 * Color sources (matched to kt-badge-* definitions in styles.css):
 *   success  → --color-green-500
 *   warning  → --color-yellow-400
 *   info     → --color-violet-500
 *   danger   → --destructive  (Metronic's own semantic destructive token)
 */

/* ── Text ─────────────────────────────────────────────────────────── */
/* Text and icons in a status colour, a shade darker on the light theme: the
   500/400 shades are 2.0:1 (green), 1.5:1 (yellow) and 4.2:1 (violet) on
   white, and an icon in them all but disappeared (2026-10-06 probe). These
   are 4.5:1 or more on white and on their own tinted panels. The dark theme
   keeps the bright shades, which already read on it. */
:root {
    --status-danger-text: var(--color-red-700);
    --status-success-text: var(--color-green-700);
    --status-warning-text: var(--color-yellow-700);
    --status-info-text: var(--color-violet-600);
}
.dark {
    --status-danger-text: #f87171; /* red-400; red-600 is 4.3:1 on the dark page */
    --status-success-text: var(--color-green-500);
    --status-warning-text: var(--color-yellow-400);
    --status-info-text: #a78bfa; /* violet-400; the build does not ship it */
}
/* Red too: --destructive (red-600) was 3.97:1 on its own red tint ("Occupied"
   on the dashboard). Buttons and badges keep --destructive behind white. */
.text-danger  { color: var(--status-danger-text); }
.text-success { color: var(--status-success-text); }
.text-warning { color: var(--status-warning-text); }
.text-info    { color: var(--status-info-text); }

/* ── Solid backgrounds ────────────────────────────────────────────── */
.bg-danger  { background-color: var(--destructive); }
.bg-success { background-color: var(--color-green-500); }
.bg-warning { background-color: var(--color-yellow-400); }
.bg-info    { background-color: var(--color-violet-500); }

/* ── Tinted backgrounds (alert boxes, stat cards) ─────────────────── */
.bg-danger\/5  { background-color: color-mix(in oklab, var(--destructive)        5%,  transparent); }
.bg-danger\/10 { background-color: color-mix(in oklab, var(--destructive)        10%, transparent); }
.bg-danger\/20 { background-color: color-mix(in oklab, var(--destructive)        20%, transparent); }

.bg-success\/5  { background-color: color-mix(in oklab, var(--color-green-500)   5%,  transparent); }
.bg-success\/10 { background-color: color-mix(in oklab, var(--color-green-500)   10%, transparent); }
.bg-success\/20 { background-color: color-mix(in oklab, var(--color-green-500)   20%, transparent); }

.bg-warning\/5  { background-color: color-mix(in oklab, var(--color-yellow-400)  5%,  transparent); }
.bg-warning\/10 { background-color: color-mix(in oklab, var(--color-yellow-400)  10%, transparent); }
.bg-warning\/20 { background-color: color-mix(in oklab, var(--color-yellow-400)  20%, transparent); }

.bg-info\/5  { background-color: color-mix(in oklab, var(--color-violet-500)  5%,  transparent); }
.bg-info\/10 { background-color: color-mix(in oklab, var(--color-violet-500)  10%, transparent); }
.bg-info\/20 { background-color: color-mix(in oklab, var(--color-violet-500)  20%, transparent); }

/* ── Borders ──────────────────────────────────────────────────────── */
.border-danger  { border-color: var(--destructive); }
.border-success { border-color: var(--color-green-500); }
.border-warning { border-color: var(--color-yellow-400); }
.border-info    { border-color: var(--color-violet-500); }

.border-danger\/10 { border-color: color-mix(in oklab, var(--destructive)        10%, transparent); }
.border-danger\/20 { border-color: color-mix(in oklab, var(--destructive)        20%, transparent); }
.border-danger\/30 { border-color: color-mix(in oklab, var(--destructive)        30%, transparent); }

.border-success\/10 { border-color: color-mix(in oklab, var(--color-green-500)   10%, transparent); }
.border-success\/20 { border-color: color-mix(in oklab, var(--color-green-500)   20%, transparent); }
.border-success\/30 { border-color: color-mix(in oklab, var(--color-green-500)   30%, transparent); }

.border-warning\/10 { border-color: color-mix(in oklab, var(--color-yellow-400)  10%, transparent); }
.border-warning\/20 { border-color: color-mix(in oklab, var(--color-yellow-400)  20%, transparent); }

.border-info\/10 { border-color: color-mix(in oklab, var(--color-violet-500)  10%, transparent); }
.border-info\/20 { border-color: color-mix(in oklab, var(--color-violet-500)  20%, transparent); }

/* ── Logical border-start (used for left-accent cards) ────────────── */
.border-s-danger   { border-inline-start-color: var(--destructive); }
.border-s-success  { border-inline-start-color: var(--color-green-500); }
.border-s-warning  { border-inline-start-color: var(--color-yellow-400); }
.border-s-info     { border-inline-start-color: var(--color-violet-500); }
.border-s-secondary { border-inline-start-color: var(--secondary); }

/* ── Hover variants ───────────────────────────────────────────────── */
.hover\:border-danger:hover  { border-color: var(--destructive); }
.hover\:border-success:hover { border-color: var(--color-green-500); }
.hover\:bg-danger\/10:hover  { background-color: color-mix(in oklab, var(--destructive)      10%, transparent); }
.hover\:bg-success\/10:hover { background-color: color-mix(in oklab, var(--color-green-500)  10%, transparent); }

/* ── kt-badge-danger alias (maps to destructive) ──────────────────── */
.kt-badge-danger {
    background-color: var(--destructive);
    color: var(--destructive-foreground);
}
.kt-badge-outline.kt-badge-danger {
    border-width: 1px;
    border-color: color-mix(in oklab, var(--destructive) 40%, transparent);
    background-color: color-mix(in oklab, var(--destructive) 10%, transparent);
    color: var(--destructive);
}
/* Red on its own red tint was 3.9:1; a shade further from the tint. */
.kt-badge-outline.kt-badge-danger,
.kt-badge-outline.kt-badge-destructive { color: var(--color-red-700); }
.dark .kt-badge-outline.kt-badge-danger,
.dark .kt-badge-outline.kt-badge-destructive { color: #f87171; /* red-400 */ }

/* ── kt-btn-danger alias ──────────────────────────────────────────── */
.kt-btn-danger {
    background-color: var(--destructive);
    color: var(--destructive-foreground);
}
.kt-btn-outline.kt-btn-danger,
.kt-btn.kt-btn-danger.kt-btn-outline {
    border-color: var(--destructive);
    color: var(--destructive);
    background-color: transparent;
}
.kt-btn-outline.kt-btn-danger:hover,
.kt-btn.kt-btn-danger.kt-btn-outline:hover {
    background-color: color-mix(in oklab, var(--destructive) 10%, transparent);
}

/* ── Input validation highlight ───────────────────────────────────── */
.kt-input.border-danger,
.kt-select.border-danger {
    border-color: var(--destructive) !important;
}

/* -- cursor-not-allowed ------------------------------------------------- */
/* The compiled Metronic build ships only .cursor-pointer, but a channel that
   cannot be delivered is shown disabled on the Settings screen and should say
   so under the pointer as well as in words. */
.cursor-not-allowed {
    cursor: not-allowed;
}

/* -- pane-divider ------------------------------------------------------- */
/* Separates the two panes of a notification row: a rule above when the panes
   are stacked, and down the side once they sit together. The compiled build
   ships border-t and border-s but no responsive variants of either, so the
   switch needs a rule of its own. Colour comes from border-border. */
.pane-divider {
    border-top-width: 1px;
    border-top-style: solid;
}

@media (min-width: 768px) {
    .pane-divider {
        border-top-width: 0;
        border-inline-start-width: 1px;
        border-inline-start-style: solid;
    }
}

/* -- utilities the compiled build does not ship -------------------------- */
/* Metronic's styles.css is a fixed precompiled build, not generated from this
   project's templates, so a Tailwind utility used here only works if that
   build happened to include it. These six did not, and the browser was asked
   rather than guessed: font-bold left "bold" text across 14 views at normal
   weight, max-w-[400px] left the sign-in card stretching to the full half of
   the screen, and the translucent whites on the banner rendered solid. Values
   are Tailwind's own, so adding the class back changes nothing else. */
.font-bold     { font-weight: 700; }
.leading-snug  { line-height: 1.375; }
.max-w-\[400px\] { max-width: 400px; }
.text-white\/70 { color: rgb(255 255 255 / 0.7); }
.text-white\/60 { color: rgb(255 255 255 / 0.6); }
.bg-white\/10   { background-color: rgb(255 255 255 / 0.1); }

/* -- tints the file was missing ----------------------------------------- */
/* These are used across the views but were never defined here, and the
   precompiled Metronic build does not ship them either, so the avatar circles
   on the dashboard, tenants, locations, structures and reports rendered with no
   background at all, and two warning panels with no border. Found by asking the
   browser which classes resolve to nothing rather than by reading templates. */
.bg-primary\/5  { background-color: color-mix(in oklab, var(--primary) 5%,  transparent); }
.bg-primary\/10 { background-color: color-mix(in oklab, var(--primary) 10%, transparent); }
.border-primary\/20 { border-color: color-mix(in oklab, var(--primary) 20%, transparent); }

.border-warning\/30 { border-color: color-mix(in oklab, var(--color-yellow-400) 30%, transparent); }
.border-warning\/40 { border-color: color-mix(in oklab, var(--color-yellow-400) 40%, transparent); }

/* -- issue-photo --------------------------------------------------------- */
/* Thumbnails of the photos attached to an issue. A fixed square with the image
   cropped to fill it, so a portrait phone photo and a landscape one line up;
   the full image opens in a new tab. The compiled build has no object-cover,
   so the crop is set here. */
.issue-photo {
    width: 96px;
    height: 96px;
    object-fit: cover;
}

/* -- whitespace-pre-line -------------------------------------------------- */
/* Keeps the line breaks somebody typed into an issue's description, a reply or
   a resolution note, while still wrapping long lines. The compiled build ships
   only whitespace-nowrap, so without this every multi-paragraph description
   collapsed into one block. */
.whitespace-pre-line {
    white-space: pre-line;
}

/* ==========================================================================
   Utilities the precompiled build does not ship
   --------------------------------------------------------------------------
   Metronic's styles.css is a fixed build, not generated from these templates,
   so a class used here only works if that build happened to include it. Each
   rule below is a class the templates already use and that resolved to nothing:
   found by asking the browser, not by reading the markup. Values are Tailwind's
   own, so adding a rule restores what was meant and changes nothing else.

   Breakpoints follow the build: sm 40rem, md 48rem, lg 64rem.
   ========================================================================== */

/* -- form grids ----------------------------------------------------------
   The biggest of these. Ten forms - new tenant, new assignment, locations,
   rooms, structures - are written as a 12-column grid with fields spanning 4,
   6 or 12. With no rule for any of it, every field sat on its own full-width
   row and the forms were several screens long. */
@media (width >= 48rem) {
    .md\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
    .md\:grid-cols-3  { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .md\:grid-cols-4  { grid-template-columns: repeat(4, minmax(0, 1fr)); }

    .md\:col-span-2  { grid-column: span 2 / span 2; }
    .md\:col-span-3  { grid-column: span 3 / span 3; }
    .md\:col-span-4  { grid-column: span 4 / span 4; }
    .md\:col-span-5  { grid-column: span 5 / span 5; }
    .md\:col-span-6  { grid-column: span 6 / span 6; }
    .md\:col-span-8  { grid-column: span 8 / span 8; }
    .md\:col-span-9  { grid-column: span 9 / span 9; }
    .md\:col-span-12 { grid-column: span 12 / span 12; }
}

@media (width >= 40rem) {
    .sm\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Stat tiles on the dashboard, reports, a location and a structure: written to
   go four or six across on a wide screen, they stopped at the two columns the
   base class gives. */
@media (width >= 64rem) {
    .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .lg\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* -- required fields -----------------------------------------------------
   70 labels across the forms carry this, expecting the usual asterisk. Without
   it nothing marked which fields were compulsory until the form was submitted.
   Scoped to a form label because "required" is too general a word to style on
   its own. */
.kt-form-label.required::after {
    content: "*";
    color: var(--destructive);
    margin-inline-start: calc(var(--spacing) * 0.5);
}

/* -- widths --------------------------------------------------------------
   Tailwind's container scale; the build ships only the 2xl this theme used. */
.max-w-xs       { max-width: 20rem; }
.max-w-3xl      { max-width: 48rem; }
.max-w-4xl      { max-width: 56rem; }
.max-w-\[180px\] { max-width: 180px; }

/* -- spacing -------------------------------------------------------------- */
.mt-0\.5 { margin-top: calc(var(--spacing) * 0.5); }
.mt-1\.5 { margin-top: calc(var(--spacing) * 1.5); }
.ms-3    { margin-inline-start: calc(var(--spacing) * 3); }
.ms-4    { margin-inline-start: calc(var(--spacing) * 4); }
.ms-6    { margin-inline-start: calc(var(--spacing) * 6); }
.p-6     { padding: calc(var(--spacing) * 6); }
.px-6    { padding-inline: calc(var(--spacing) * 6); }
.py-6    { padding-block: calc(var(--spacing) * 6); }
.py-8    { padding-block: calc(var(--spacing) * 8); }
.gap-x-8   { column-gap: calc(var(--spacing) * 8); }
.gap-y-0\.5 { row-gap: calc(var(--spacing) * 0.5); }
.gap-y-1   { row-gap: calc(var(--spacing) * 1); }

/* Space between children, rather than around them. */
.space-y-0\.5 > * + * { margin-top: calc(var(--spacing) * 0.5); }

/* -- sizes ---------------------------------------------------------------- */
.size-18 { width: calc(var(--spacing) * 18); height: calc(var(--spacing) * 18); }
.h-fit   { height: fit-content; }
.text-5xl      { font-size: 3rem; line-height: 1; }
.text-\[8px\]  { font-size: 8px; line-height: 1; }
.text-\[9px\]  { font-size: 9px; line-height: 1; }

/* -- type ----------------------------------------------------------------- */
.capitalize      { text-transform: capitalize; }
.tracking-wide   { letter-spacing: 0.025em; }
.tracking-widest { letter-spacing: 0.1em; }
.font-mono       { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; }
.list-disc       { list-style-type: disc; }
.list-inside     { list-style-position: inside; }
.no-underline    { text-decoration-line: none; }

/* -- state and effect ----------------------------------------------------- */
.opacity-30 { opacity: 0.3; }
.opacity-60 { opacity: 0.6; }
.select-none    { -webkit-user-select: none; user-select: none; }
.cursor-default { cursor: default; }
.transition-shadow {
    transition-property: box-shadow;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
}
.last\:border-b-0:last-child { border-bottom-style: var(--tw-border-style, solid); border-bottom-width: 0; }

/* Tinted accents, the same way the semantic tints above are built. */
.bg-accent\/20 { background-color: color-mix(in oklab, var(--accent) 20%, transparent); }
.bg-accent\/30 { background-color: color-mix(in oklab, var(--accent) 30%, transparent); }
.bg-accent\/40 { background-color: color-mix(in oklab, var(--accent) 40%, transparent); }

/* Hover, guarded as the build guards its own: a device without a pointer
   should not get a state it can never leave. */
@media (hover: hover) {
    .hover\:bg-accent\/40:hover  { background-color: color-mix(in oklab, var(--accent) 40%, transparent); }
    .hover\:border-warning:hover { border-color: var(--color-yellow-400); }
    .hover\:underline:hover      { text-decoration-line: underline; }
    .hover\:shadow-md:hover {
        box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
    }
}

/* -- the avatar gradient on a tenant's page ------------------------------- */
.bg-gradient-to-br {
    background-image: linear-gradient(to bottom right,
        var(--tw-gradient-from, transparent), var(--tw-gradient-to, transparent));
}
.from-primary   { --tw-gradient-from: var(--primary); }
.to-purple-500  { --tw-gradient-to: oklch(62.7% 0.265 303.9); }

/* -- button variants the build does not include ---------------------------
   Written like .kt-btn-destructive, which is the pattern the build uses. The
   background is a step darker than the text colour of the matching
   .text-success / .text-warning, because white on the lighter shade is not
   legible - the same reason those two are on the contrast list. */
.kt-btn-success {
    background-color: var(--color-green-700);
    color: var(--color-white);
}
.kt-btn-warning {
    background-color: var(--color-yellow-700);
    color: var(--color-white);
}
@media (hover: hover) {
    .kt-btn-success:hover { background-color: var(--color-green-800); }
    .kt-btn-warning:hover { background-color: var(--color-yellow-800); }
}

/* -- checkbox labels -----------------------------------------------------
   Deliberately no font-size: several of these also carry text-sm, and a size
   here would override it, since this file is loaded after the build's. */
.kt-checkbox-label {
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}

/* -- phone widths --------------------------------------------------------
   A table must never widen the page. Before this, one wide table made the
   whole page wider than the phone (908px on /tenants at 375px), the fixed
   header stretched with it, and the user menu - Sign Out included - opened
   off the right edge of the screen. The layout wrappers carry min-w-0 for the
   same reason. Cards are flex and grid items, so they need min-width: 0 to
   fit their column rather than their widest row; the table then scrolls
   sideways inside its card. */
.kt-card { min-width: 0; }
.kt-card-content:has(> table) { overflow-x: auto; }

/* Below lg the sidebar is a drawer and these are the controls a thumb has to
   hit. 44px is the WCAG 2.5.5 / Apple HIG minimum; the build's icon buttons
   are 34px and its small ones 28px. The drawer toggle is sized in the
   template (it only exists below lg); desktop keeps the build's sizes. */
@media (width < 64rem) {
    #user_menu_toggle { height: 2.75rem; }
    #sidebar_footer form button { width: 2.75rem; height: 2.75rem; }

    /* In the drawer the menu is ~740px tall and was shrink-0, so on any phone
       shorter than that the footer - name, role and Sign Out - sat below the
       bottom of a fixed panel that cannot scroll, and so did the last menu
       items. Letting the menu shrink and scroll keeps the footer on screen. */
    #sidebar_content, #sidebar_scrollable { flex-shrink: 1; min-height: 0; }
    #sidebar_scrollable { overflow-y: auto; }
}

/* -- the System Status page ----------------------------------------------
   Utilities its markup uses that the precompiled build does not ship, found
   by asking the browser (2026-10-05). A long address or error message wraps
   inside its row instead of widening the page on a phone, and a job's output
   keeps its own lines and scrolls sideways inside its box. */
.wrap-break-word { overflow-wrap: break-word; }
.whitespace-pre  { white-space: pre; }
.overflow-x-auto { overflow-x: auto; }

/* -- seeing the controls (2026-10-06) -------------------------------------
   Measured across 25 pages in both themes before this section: every input,
   select and outline button had a border at 1.27:1 (light) / 1.34:1 (dark)
   against its card, so an empty field and the row of eye / pencil / bin
   buttons in each table were barely there. WCAG 1.4.11 asks 3:1 for what
   identifies a control. --input is the build's token for exactly those
   borders (inputs, selects, textareas, outline buttons, checkboxes, radios,
   the switch track), so it is the one value changed: focus and hover rules
   keep working as they were. */
:root { --input: #8c8c95; }  /* 3.3:1 on white */
.dark { --input: #62626b; }  /* 3.3:1 on the dark card */

/* White words on the build's mid-tone badges were 1.6:1 (warning), 2.2:1
   (success) and 4.4:1 (info). Yellow keeps its colour and takes dark words. */
.kt-badge-success { background-color: var(--color-green-700); color: var(--color-white); }
.kt-badge-warning { background-color: var(--color-yellow-400); color: var(--color-zinc-950); }
.kt-badge-info    { background-color: var(--color-violet-600); color: var(--color-white); }

/* White on the light theme's primary (blue-500) was 3.8:1 on every primary
   button, and blue-500 words on white the same. blue-600 is 5.2:1, and is
   already the dark theme's primary, so both themes now use one blue. */
:root { --primary: var(--color-blue-600); }
/* On the dark theme blue-600 words were 3.8:1 against the page; buttons keep
   blue-600 behind white, words in primary are a lighter blue. */
.dark .text-primary { color: #60a5fa; /* blue-400 */ }

/* -- phones and touch screens ----------------------------------------------
   Below md, or with a finger rather than a mouse at any width. Before this,
   on a 375px phone the table action buttons were 28px (some 20px), every
   small button 28px tall and every field 34px; 44px is the WCAG 2.5.5 /
   Apple HIG minimum for a thumb. Fields were 13px text, which iOS answers by
   zooming the page into the field and not zooming back out; at 16px it does
   not. Rows of a table grow taller on a phone as a result, which is the
   price of being able to hit the right one. */
@media (pointer: coarse), (width < 48rem) {
    .kt-btn { min-height: 2.75rem; }
    .kt-btn-icon { min-width: 2.75rem; }
    /* The small table buttons' glyphs only: an icon button sized in its
       template (the 20px drawer toggle) keeps its own glyph. */
    .kt-btn-icon.kt-btn-sm > i { font-size: 1.125rem; }

    .kt-input, .kt-select, .kt-textarea { min-height: 2.75rem; }
    .kt-input, .kt-select, .kt-textarea,
    input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
    select, textarea { font-size: 1rem; }

    /* A name in a table cell is the row's way in, and a breadcrumb is the way
       back: a thumb's height to tap, without moving the text (the padding is
       given back as negative margin). Links laid out by flex or grid keep
       their own box. */
    :is(.kt-table td, #breadcrumb) a:not(.kt-btn):not(.kt-badge):not(.flex):not(.inline-flex):not(.block):not(.grid) {
        display: inline-block;
        padding-block: 0.75rem;
        margin-block: -0.75rem;
    }

    /* A field drawn as a box around an icon and an input (the search boxes):
       the whole 44px box takes the tap, not just the 23px line of text. */
    .kt-input > input, .kt-input > select { align-self: stretch; }

    /* In a table squeezed to the phone a select shrank to 32px, too narrow to
       read its choice; the table scrolls sideways inside its card instead. */
    .kt-table td .kt-select { min-width: 9rem; }

    #sidebar .kt-menu-link { min-height: 2.75rem; }
}

/* -- 320px phones (found by the 320px crawl, 2026-10-06) ------------------
   The breadcrumb was one row that could not wrap: "Dashboard > Assignments >
   ASN-6A1D96C0D43AD" made an assignment's page 323px wide. And two issue
   tiles a row left ~26px beside each icon, so "Awaiting confirmation" pushed
   /issues to 322px; below 30rem the number and its label go under the icon. */
#breadcrumb { flex-wrap: wrap; row-gap: 0.25rem; }
@media (width < 30rem) {
    #issue-tiles > a > .flex { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
}

/* -- deleting a payment (2026-10-07) ----------------------------------------
   The delete form sits in a row that spans the whole table, and on a phone
   the table is wider than the screen and scrolls sideways inside its card:
   the reason field ran 843px wide on a 375px phone, its middle off the
   screen. The form keeps to the screen's width and to the left edge of the
   card, however far the table has been scrolled to reach the trash button. */
form[data-payment-delete] {
    position: sticky;
    left: 1rem;
    max-width: calc(100vw - 4rem);
}
