/* ==========================================================================
   AI Accounting — shared design system
   Loaded last on every page, so it standardises what the per-page inline
   styles and Tailwind utilities left inconsistent.

   1. Tokens          2. Base / reset      3. Typography
   4. Layout          5. Sidebar           6. Buttons
   7. Tables          8. Forms             9. Cards & headers
  10. Utilities      11. Print
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */
:root {
  /* Brand — kept from the existing indigo/violet identity */
  --aia-primary:        #4f46e5;
  --aia-primary-hover:  #4338ca;
  --aia-primary-soft:   #eef2ff;
  --aia-accent:         #7c3aed;

  /* Semantic */
  --aia-success:        #059669;
  --aia-success-soft:   #ecfdf5;
  --aia-warning:        #d97706;
  --aia-warning-soft:   #fffbeb;
  --aia-danger:         #dc2626;
  --aia-danger-soft:    #fef2f2;
  --aia-info:           #0284c7;
  --aia-info-soft:      #f0f9ff;

  /* Neutrals */
  --aia-bg:             #f6f7fb;
  --aia-surface:        #ffffff;
  --aia-border:         #e4e7ec;
  --aia-border-strong:  #cbd2dc;
  --aia-text:           #101828;
  --aia-text-muted:     #667085;
  --aia-text-subtle:    #98a2b3;

  /* Type scale */
  --aia-fs-xs:   0.75rem;    /* 12 */
  --aia-fs-sm:   0.8125rem;  /* 13 */
  --aia-fs-base: 0.9375rem;  /* 15 */
  --aia-fs-md:   1rem;       /* 16 */
  --aia-fs-lg:   1.125rem;   /* 18 */
  --aia-fs-xl:   1.25rem;    /* 20 */

  /* Spacing */
  --aia-sp-1: 0.25rem;
  --aia-sp-2: 0.5rem;
  --aia-sp-3: 0.75rem;
  --aia-sp-4: 1rem;
  --aia-sp-5: 1.5rem;
  --aia-sp-6: 2rem;

  /* Shape */
  --aia-radius-sm: 6px;
  --aia-radius:    10px;
  --aia-radius-lg: 14px;

  --aia-shadow-sm: 0 1px 2px rgba(16, 24, 40, .05);
  --aia-shadow:    0 1px 3px rgba(16, 24, 40, .08), 0 1px 2px rgba(16, 24, 40, .04);
  --aia-shadow-lg: 0 8px 24px -6px rgba(16, 24, 40, .12), 0 2px 6px rgba(16, 24, 40, .05);

  /* Controls */
  --aia-control-h:    2.375rem;  /* 38px — the one button/input height   */
  --aia-control-h-sm: 2rem;      /* 32px — compact, for in-table actions */

  --aia-header-h: 56px;          /* mobile top bar */
}

/* ---------- 2. Base / reset --------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: var(--aia-fs-base);
  line-height: 1.55;
  color: var(--aia-text);
  /* Nothing may scroll the page sideways. Wide content scrolls inside itself. */
  overflow-x: hidden;
}

/* Media never overflows its column. */
img, svg, video, canvas, iframe { max-width: 100%; height: auto; }

/* Long unbroken strings (account codes, URLs, emails) wrap instead of pushing.
   Scoped to text containers — applying this broadly made button labels break
   one character per line inside narrow columns. */
body :is(td, th, p, li, dd, dt) { overflow-wrap: break-word; }

/* Controls and their labels never break mid-word. */
body :is(button, .btn, label, th, a[class*="px-"]) ,
body :is(button, .btn, a[class*="px-"]) * {
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}

:focus-visible {
  outline: 2px solid var(--aia-primary);
  outline-offset: 2px;
  border-radius: var(--aia-radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-delay: 0s !important;          /* staggered entrances otherwise
                                                sit off-screen for their delay */
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* Entrance animations must never leave content parked outside the viewport:
   if the animation never runs (reduced motion, print, a JS error), the element
   must still be in its final, visible position. */
body :is([class*="slide-in"], [class*="fade-in"], [class*="stagger"]) {
  /* `forwards`, not `both`: with `both` the element holds its *start* position
     for the whole stagger delay, which parked the later cards off-screen to
     the left. `forwards` only keeps the finished state. */
  animation-fill-mode: forwards;
}
@media (prefers-reduced-motion: reduce), print {
  body :is([class*="slide-in"], [class*="fade-in"], [class*="stagger"]) {
    animation: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
}

/* ---------- 3. Typography ------------------------------------------------ */
/* Page titles were text-3xl/4xl/5xl on different pages. One responsive scale. */
body :is(h1, .page-title, .text-4xl, .text-5xl) { font-size: clamp(1.35rem, 1.05rem + 1.2vw, 1.75rem); line-height: 1.25; }
body :is(h2, .text-3xl)                          { font-size: clamp(1.2rem,  1rem   + 0.8vw, 1.5rem);  line-height: 1.3;  }
body :is(h3, .text-2xl)                          { font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.25rem); line-height: 1.35; }
body :is(h4, .text-xl)                           { font-size: 1.0625rem; line-height: 1.4; }
body .text-lg                                    { font-size: var(--aia-fs-lg); }
body .text-base                                  { font-size: var(--aia-fs-md); }
body .text-sm                                    { font-size: var(--aia-fs-sm); }
body .text-xs                                    { font-size: var(--aia-fs-xs); }

body :is(h1, h2, h3, h4, h5, h6) {
  text-wrap: balance;
  font-weight: 600;
  letter-spacing: -0.011em;
}

/* Figures line up in columns. */
body :is(td, th, .tabular, .amount, .num) { font-variant-numeric: tabular-nums; }

/* ---------- 4. Layout ---------------------------------------------------- */
/* sidebar.css carries a "FINAL LOCK" block:
       body .content-area { margin-left:280px !important; width:calc(100vw - 280px) !important }
   Its own mobile override is written as `.content-area` — lower specificity than
   `body .content-area`, so it never won and the content stayed pushed 280px to
   the right on every phone and tablet. These rules use `html body` to outrank it.
   Using 100vw was also wrong: it includes the scrollbar, so the row overflowed. */
html body :is(.content-area, .main-content) {
  margin-left: var(--sidebar-width, 280px) !important;
  width: auto !important;
  max-width: none !important;
  padding: clamp(0.875rem, 0.4rem + 1.6vw, 1.75rem) !important;
}

/* Clear the sidebar exactly once. sidebar.css also offsets <body>, so a page
   that has both the body class and a content wrapper was indented twice and
   ran 280px off the right edge. Where a wrapper exists, it owns the offset;
   pages without one keep the offset on <body>. */
html body.has-app-sidebar:has(:is(.content-area, .main-content)) {
  margin-left: 0 !important;
}

/* Pages that never adopted .content-area still get sane gutters. */
body.has-app-sidebar > :is(main, .container, .wrapper, .page) {
  padding-inline: clamp(0.875rem, 0.4rem + 1.6vw, 1.75rem);
}

/* Keep dense report pages readable on very wide monitors. */
@media (min-width: 1800px) {
  html body :is(.content-area, .main-content) > * { max-width: 1600px; }
}

/* Standard block rhythm for the common Tailwind paddings, scaled down on small screens. */
@media (max-width: 640px) {
  body :is(.p-8, .p-6)  { padding: var(--aia-sp-4) !important; }
  body :is(.p-5, .p-4)  { padding: var(--aia-sp-3) !important; }
  body :is(.px-8, .px-6){ padding-inline: var(--aia-sp-4) !important; }
  body :is(.py-8, .py-6){ padding-block:  var(--aia-sp-4) !important; }
  body .gap-6           { gap: var(--aia-sp-3) !important; }
  body :is(.mb-8, .mb-6){ margin-bottom: var(--aia-sp-4) !important; }
}

/* Grids collapse rather than squeeze. */
@media (max-width: 900px) {
  body :is(.grid-cols-3, .grid-cols-4, .grid-cols-5, .grid-cols-6) { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 600px) {
  body :is(.grid-cols-2, .grid-cols-3, .grid-cols-4, .grid-cols-5, .grid-cols-6) { grid-template-columns: 1fr !important; }
}

/* ---------- 5. Sidebar --------------------------------------------------- */
/* The mobile rules already existed but were defeated by inline styles from
   sidebar.php and by an !important margin on body. Both are corrected here. */

.aia-topbar { display: none; }

@media (max-width: 1024px) {
  .aia-topbar {
    display: flex;
    align-items: center;
    gap: var(--aia-sp-3);
    position: fixed;
    inset: 0 0 auto 0;
    height: var(--aia-header-h);
    padding-inline: var(--aia-sp-3);
    background: #0f172a;
    color: #fff;
    z-index: 1002;
    box-shadow: var(--aia-shadow);
  }

  .aia-topbar__title { font-size: var(--aia-fs-md); font-weight: 600; letter-spacing: -0.01em; }

  .aia-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    flex: 0 0 40px;
    border: 1px solid rgba(255,255,255,.18);
    border-radius: var(--aia-radius-sm);
    background: rgba(255,255,255,.08);
    color: #fff;
    font-size: 1.05rem;
    cursor: pointer;
  }
  .aia-burger:hover { background: rgba(255,255,255,.16); }

  /* Off-canvas, and beat the inline styles sidebar.php used to write. */
  body .modern-sidebar,
  body aside.modern-sidebar {
    transform: translateX(-100%) !important;
    transition: transform .24s ease !important;
    width: min(300px, 86vw) !important;
    min-width: 0 !important;
    max-width: 86vw !important;
    z-index: 1003 !important;
  }
  body .modern-sidebar.mobile-open,
  body aside.modern-sidebar.mobile-open { transform: translateX(0) !important; }

  /* The base rules set these with !important, so the resets need to outrank them. */
  html body.has-app-sidebar { margin-left: 0 !important; }

  html body :is(.content-area, .main-content) {
    margin-left: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    /* Clear the fixed top bar. */
    padding: calc(var(--aia-header-h) + var(--aia-sp-3)) var(--aia-sp-3) var(--aia-sp-5) !important;
  }

  html body.has-app-sidebar > main { padding-top: calc(var(--aia-header-h) + var(--aia-sp-3)); }

  .aia-scrim {
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, .5);
    backdrop-filter: blur(2px);
    z-index: 1002;
    opacity: 0; pointer-events: none;
    transition: opacity .2s ease;
  }
  .aia-scrim.active { opacity: 1; pointer-events: auto; }

  body.aia-nav-open { overflow: hidden; }

  /* The floating back-to-top button collides with the burger. */
  .back-to-top-btn { display: none !important; }
}

/* Smoother nav interaction on pointer devices. */
@media (min-width: 1025px) and (prefers-reduced-motion: no-preference) {
  .modern-sidebar .nav-item { transition: background-color .15s ease, transform .15s ease; }
  .modern-sidebar .nav-item:hover { transform: translateX(2px); }
}

.modern-sidebar .nav-item:focus-visible { outline: 2px solid #fbbf24; outline-offset: -2px; }

/* ---------- 6. Buttons --------------------------------------------------- */
/* One height, one radius, one weight. Only elements that already carry a
   px-/py- utility are touched, so icon-only square buttons keep their sizing. */
body :is(button, a, input[type="submit"], input[type="button"])[class*="px-"][class*="py-"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--aia-sp-2);
  min-height: var(--aia-control-h);
  padding-block: 0 !important;
  padding-inline: var(--aia-sp-4) !important;
  font-size: var(--aia-fs-sm) !important;
  font-weight: 500;
  line-height: 1.2;
  border-radius: var(--aia-radius) !important;
  white-space: nowrap;
  /* A button is never narrower than its own label. Without this, a button
     dropped into a tight grid column collapsed into a vertical letter stack. */
  min-width: fit-content;
  flex-shrink: 0;
  cursor: pointer;
  transition: filter .15s ease, box-shadow .15s ease, transform .15s ease;
}

/* Compact variants keep a smaller footprint. */
body :is(button, a)[class*="px-2"][class*="py-1"],
body :is(button, a)[class*="px-3"][class*="py-1"] {
  min-height: var(--aia-control-h-sm);
  padding-inline: var(--aia-sp-3) !important;
  font-size: var(--aia-fs-xs) !important;
}

body :is(button, a)[class*="px-"][class*="py-"]:hover:not(:disabled) { filter: brightness(.94); }
body :is(button, a)[class*="px-"][class*="py-"]:active:not(:disabled) { transform: translateY(1px); }
body button:disabled,
body button[disabled] { opacity: .55; cursor: not-allowed; filter: none !important; }

/* Icon-only buttons: perfectly centred, consistent radius. */
body :is(button, a)[class*="w-8"][class*="h-8"],
body :is(button, a)[class*="w-9"][class*="h-9"],
body :is(button, a)[class*="w-10"][class*="h-10"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  border-radius: var(--aia-radius-sm);
}

/* Several pages use their own .modern-btn / .btn classes rather than utilities.
   They get the same height, radius and label protection. */
body :is(.modern-btn, .btn, .action-btn) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--aia-sp-2);
  min-height: var(--aia-control-h);
  padding-inline: var(--aia-sp-4);
  font-size: var(--aia-fs-sm);
  font-weight: 500;
  border-radius: var(--aia-radius);
  white-space: nowrap;
  min-width: fit-content;
  text-overflow: clip;
}

/* A grid cell holding buttons must not be squeezed below its own content, but
   it must never widen the track either — forcing max-content here blew whole
   `xl:col-span-*` layouts past the viewport. min-content is the safe floor:
   the buttons stack instead of the grid growing. */
body [class*="col-span-"]:has(:is(.modern-btn, .btn, button, a[class*="px-"])) {
  min-width: 0;
}

/* Button rows wrap instead of overflowing on narrow screens. */
body :is(.flex, .inline-flex):has(> :is(button, a[class*="px-"], .modern-btn, .btn)) { flex-wrap: wrap; }

/* Grid and flex children default to min-width:auto, which refuses to shrink
   below their content and is the usual cause of a layout pushing sideways. */
body :is([class*="grid-cols-"], .grid) > * { min-width: 0; }
body :is(.flex, .inline-flex) > :not(:is(button, a[class*="px-"], .modern-btn, .btn)) { min-width: 0; }

/* Pagination and other deep button groups wrap too, rather than running off
   both edges of a phone. */
@media (max-width: 900px) {
  html body .content-area :is(.flex, .inline-flex):has(:is(button, a[class*="px-"], .modern-btn, .btn)) {
    flex-wrap: wrap;
    row-gap: var(--aia-sp-2);
  }
}

@media (max-width: 640px) {
  /* Full-width actions read better on a phone than a row of stubs. */
  body .content-area :is(button, a)[class*="px-"][class*="py-"]:not([class*="w-"]) { flex: 1 1 auto; }
}

/* ---------- 7. Tables ---------------------------------------------------- */
/* aia.js wraps every bare table in this, so wide reports scroll inside
   themselves and never push the page sideways. */
.aia-table-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--aia-radius);
  scrollbar-width: thin;
}
.aia-table-scroll > table { min-width: max-content; }
.aia-table-scroll::-webkit-scrollbar { height: 8px; }
.aia-table-scroll::-webkit-scrollbar-thumb { background: var(--aia-border-strong); border-radius: 99px; }

body table { border-collapse: collapse; width: 100%; font-size: var(--aia-fs-sm); }
body :is(th, td) { padding: 0.625rem 0.75rem; vertical-align: middle; }
body th { font-weight: 600; text-align: left; white-space: nowrap; }
body tbody tr { border-bottom: 1px solid var(--aia-border); }
body tbody tr:last-child { border-bottom: 0; }

/* Keep sticky headers usable inside the scroll container. */
body thead th { position: sticky; top: 0; z-index: 1; background: inherit; }

/* ---------- 8. Forms ----------------------------------------------------- */
body :is(input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]),
         select, textarea) {
  min-height: var(--aia-control-h);
  padding: 0.4375rem 0.75rem;
  font-size: var(--aia-fs-base);
  font-family: inherit;
  color: var(--aia-text);
  background: var(--aia-surface);
  border: 1px solid var(--aia-border-strong);
  border-radius: var(--aia-radius-sm);
  width: 100%;
  max-width: 100%;
  transition: border-color .15s ease, box-shadow .15s ease;
}
body textarea { min-height: 5rem; padding-block: 0.5rem; }

body :is(input, select, textarea):focus {
  outline: none;
  border-color: var(--aia-primary);
  box-shadow: 0 0 0 3px rgba(79, 70, 229, .14);
}
body :is(input, select, textarea):disabled { background: #f2f4f7; color: var(--aia-text-subtle); }
body ::placeholder { color: var(--aia-text-subtle); }

body :is(input[type="checkbox"], input[type="radio"]) {
  width: 1rem; height: 1rem; accent-color: var(--aia-primary); cursor: pointer;
}
body label { font-size: var(--aia-fs-sm); font-weight: 500; color: var(--aia-text); }

/* iOS zooms the page when a field under 16px is focused. */
@media (max-width: 640px) {
  body :is(input, select, textarea) { font-size: 16px; }
}

/* ---------- 9. Cards & page headers -------------------------------------- */
body :is(.card, .glass-card, .bg-white[class*="rounded"][class*="shadow"]) {
  background: var(--aia-surface);
  border: 1px solid var(--aia-border);
  border-radius: var(--aia-radius-lg);
  box-shadow: var(--aia-shadow);
}

/* The gradient banner at the top of most pages. */
body :is(.page-header, [class*="bg-gradient-to-r"][class*="rounded"]) {
  border-radius: var(--aia-radius-lg);
}
@media (max-width: 640px) {
  body [class*="bg-gradient-to-r"][class*="rounded"] { padding: var(--aia-sp-4) !important; }
}

/* ---------- 9b. Modals & popups ------------------------------------------ */
/* The overlays are `fixed inset-0 flex items-center justify-center p-4`, which
   is a sound pattern, but almost none of them capped their height. A tall form
   on a short screen pushed its own Save button off-screen with no way to reach
   it. Every overlay now scrolls, and its panel is capped to the viewport. */
body :is(.modal-backdrop, .modal-overlay, .image-modal-overlay),
body [class*="fixed"][class*="inset-0"][class*="flex"] {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--aia-sp-4);
  align-items: flex-start;
}

/* Centre it again once there is room to centre it in. */
@media (min-height: 720px) {
  body :is(.modal-backdrop, .modal-overlay, .image-modal-overlay),
  body [class*="fixed"][class*="inset-0"][class*="items-center"] { align-items: center; }
}

body :is(.modal-container, .modal-content, .image-modal-content),
body :is(.modal-backdrop, .modal-overlay) > :is(div, form, section) {
  max-height: calc(100vh - 2 * var(--aia-sp-4));
  max-height: calc(100dvh - 2 * var(--aia-sp-4));
  overflow-y: auto;
  overscroll-behavior: contain;
  width: 100%;
}

/* A modal's own header and footer stay put while the body scrolls. */
body :is(.modal-container, .modal-content) > :is(.modal-header, .modal-footer) {
  position: sticky;
  background: var(--aia-surface);
  z-index: 2;
}
body :is(.modal-container, .modal-content) > .modal-header { top: 0; }
body :is(.modal-container, .modal-content) > .modal-footer { bottom: 0; }

@media (max-width: 640px) {
  /* Full-bleed sheets read better than a cramped centred card on a phone. */
  body :is(.modal-container, .modal-content) { border-radius: var(--aia-radius-lg); }
  body :is(.modal-backdrop, .modal-overlay) { padding: var(--aia-sp-2); }
}

/* Dropdown menus must not run off the right edge. */
body :is(.dropdown-menu, [id$="-menu"], [id$="-dropdown"]) {
  max-width: calc(100vw - var(--aia-sp-4));
  max-height: min(70vh, 32rem);
  overflow-y: auto;
}

/* Toasts and notification bubbles sit inside the viewport on every screen. */
body :is(#notification-box, .toast, .notification) {
  max-width: calc(100vw - var(--aia-sp-4));
  word-break: break-word;
}

body.aia-modal-open { overflow: hidden; }

/* Status pills read at a glance. */
.aia-pill {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 0.125rem 0.5rem;
  font-size: var(--aia-fs-xs); font-weight: 600;
  border-radius: 99px; white-space: nowrap;
}
.aia-pill--ok      { background: var(--aia-success-soft); color: var(--aia-success); }
.aia-pill--warn    { background: var(--aia-warning-soft); color: var(--aia-warning); }
.aia-pill--danger  { background: var(--aia-danger-soft);  color: var(--aia-danger);  }
.aia-pill--info    { background: var(--aia-info-soft);    color: var(--aia-info);    }

/* ---------- 10. Utilities ------------------------------------------------ */
.aia-only-mobile  { display: none; }
.aia-only-desktop { display: initial; }
@media (max-width: 1024px) {
  .aia-only-mobile  { display: initial; }
  .aia-only-desktop { display: none; }
}

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

/* ---------- 11. Print ---------------------------------------------------- */
@media print {
  .modern-sidebar, .aia-topbar, .aia-scrim, .back-to-top-btn,
  .no-print, [class*="sidebar"] { display: none !important; }
  body.has-app-sidebar { margin-left: 0 !important; }
  .content-area { padding: 0 !important; max-width: none !important; }
  .aia-table-scroll { overflow: visible !important; }
  body { font-size: 11pt; }
  a[href]::after { content: ""; }
}

/* ---------- 11b. Full-height app shells ----------------------------------
   The AI Assistant lays its three columns out as
       <div class="flex h-[calc(100vh-120px)]">
   with each column capped at calc(100vh - 240px) / calc(100vh - 320px).

   Three things go wrong with that:
     1. 120px is a guess at the header height. The real gradient header is
        taller, so the row runs past the bottom of the window and the right
        column's last cards are cut off.
     2. 100vh ignores mobile browser chrome and our own 56px top bar.
     3. A scroll container that centres its content with `items-center` pushes
        any overflow *upwards*, out of reach — which is why the welcome text
        was clipped mid-sentence at the top.

   aia.js measures the real offset into --aia-shell-offset; these rules use it,
   switch to dvh, and use `safe` centring so overflow always stays reachable. */

body [class*="h-[calc(100vh"] {
  height: calc(100vh - var(--aia-shell-offset, 120px)) !important;
  height: calc(100dvh - var(--aia-shell-offset, 120px)) !important;
  min-height: 320px;
}

/* Let the flex parent govern the columns rather than a second 100vh guess. */
body [class*="h-[calc(100vh"] [style*="max-height: calc(100vh"],
body [class*="h-[calc(100vh"] [style*="max-height:calc(100vh"] {
  max-height: none !important;
  min-height: 0 !important;
}

/* Safe centring: centre when it fits, align to the start when it does not, so
   the top of the content is never scrolled out of reach. */
body :is(.overflow-y-auto, [class*="overflow-y-auto"]).flex.items-center { align-items: safe center; }
body :is(.overflow-y-auto, [class*="overflow-y-auto"]).flex.justify-center { justify-content: safe center; }
body :is(.modal-container, .modal-content).flex.items-center { align-items: safe center; }

@media (max-width: 1024px) {
  /* Three side-by-side columns do not fit a phone or a tablet — stack them. */
  body [class*="h-[calc(100vh"] {
    height: auto !important;
    min-height: 0;
    flex-direction: column;
  }
  body [class*="h-[calc(100vh"] > * {
    width: 100% !important;
    max-width: 100% !important;
    flex: 0 0 auto !important;
  }
  body [class*="h-[calc(100vh"] [style*="max-height: calc(100vh"],
  body [class*="h-[calc(100vh"] [style*="max-height:calc(100vh"] {
    max-height: 65vh !important;
    max-height: 65dvh !important;
  }
}

/* ---------- 12. Mobile layout reset (last word) --------------------------
   Appended deliberately at the end of the file: the earlier mobile rule uses
   the same selector as the desktop one, and on at least one page the desktop
   declaration was still winning. Higher specificity plus last position makes
   this unambiguous. */
@media (max-width: 1024px) {
  html body.has-app-sidebar .content-area,
  html body.has-app-sidebar .main-content,
  html body .content-area,
  html body .main-content {
    margin-left: 0 !important;
    margin-right: 0 !important;
    width: auto !important;
    max-width: 100% !important;
    padding: calc(var(--aia-header-h) + var(--aia-sp-3)) var(--aia-sp-3) var(--aia-sp-5) !important;
  }
  html body.has-app-sidebar { margin-left: 0 !important; }
}

/* ---------- 13. Very narrow screens --------------------------------------
   Buttons hold `min-width: fit-content` so a tight grid cell cannot collapse
   their label into a letter stack. Below 480px a long label can still be wider
   than the whole screen, so there the label wraps instead. */
@media (max-width: 480px) {
  body :is(button, a, input[type="submit"], input[type="button"], .modern-btn, .btn)[class*="px-"] ,
  body :is(.modern-btn, .btn) {
    min-width: 0 !important;
    max-width: 100%;
    white-space: normal;
    text-align: center;
    height: auto;
    line-height: 1.3;
    padding-block: var(--aia-sp-2) !important;
  }
  body :is([class*="col-span-"], .grid > *, .flex > *) { min-width: 0 !important; }
}

/* ==========================================================================
   14. CONTROL NORMALISATION (final word)
   Measured across all 53 pages, the app was rendering 18 different button
   heights, 4 button font sizes, 5 button radii, 9 input heights, 4 card radii
   and two different body font sizes. The earlier rules only matched controls
   that happened to carry a px-/py- utility; everything using .modern-btn, a
   bare py-4, or its own inline padding slipped through. These selectors cover
   every control and are last in the file so they settle the cascade.
   ========================================================================== */

/* --- one base font size, everywhere --- */
html body { font-size: var(--aia-fs-base); }

/* --- one control height, radius and label size --- */
html body :is(
  button, .btn, .modern-btn, .action-btn,
  input[type="submit"], input[type="button"], input[type="reset"],
  a[class*="px-"], a[class*="btn"]
):not(.aia-burger):not(.back-to-top-btn):not(.nav-item):not([class*="rounded-full"]) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--aia-sp-2);
  min-height: var(--aia-control-h);
  height: auto;
  padding-block: 0 !important;
  padding-inline: var(--aia-sp-4) !important;
  font-size: var(--aia-fs-sm) !important;
  font-weight: 500;
  line-height: 1.2;
  border-radius: var(--aia-radius) !important;
  cursor: pointer;
}

/* Square icon buttons stay square; round ones stay round. */
html body :is(button, a)[class*="rounded-full"] { border-radius: 9999px !important; }
html body :is(button, a):is([class*="w-8"], [class*="w-9"], [class*="w-10"], [class*="w-11"]):is([class*="h-8"], [class*="h-9"], [class*="h-10"], [class*="h-11"]) {
  padding-inline: 0 !important;
  min-height: 0;
  aspect-ratio: 1;
}

/* Compact in-table actions keep a smaller footprint. */
html body :is(button, a)[class*="text-xs"]:not([class*="rounded-full"]) {
  min-height: var(--aia-control-h-sm);
  padding-inline: var(--aia-sp-3) !important;
  font-size: var(--aia-fs-xs) !important;
}

/* Sidebar navigation is its own component — leave it alone. */
html body .modern-sidebar :is(a, button) {
  min-height: 0;
  padding-inline: revert !important;
  font-size: revert !important;
  border-radius: revert !important;
}

/* --- one field height and radius --- */
html body :is(input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]), select) {
  min-height: var(--aia-control-h) !important;
  padding-block: 0 !important;
  padding-inline: var(--aia-sp-3) !important;
  font-size: var(--aia-fs-base);
  border-radius: var(--aia-radius-sm) !important;
}
html body textarea {
  min-height: 5rem;
  padding: var(--aia-sp-2) var(--aia-sp-3) !important;
  font-size: var(--aia-fs-base);
  border-radius: var(--aia-radius-sm) !important;
}
@media (max-width: 640px) {
  /* iOS zooms on focus below 16px. */
  html body :is(input, select, textarea) { font-size: 16px; }
}

/* --- one card radius --- */
html body :is(.card, .glass-card, [class*="rounded-xl"], [class*="rounded-2xl"], [class*="rounded-3xl"]):not(button):not(a):not(input):not([class*="w-8"]):not([class*="w-10"]):not([class*="w-12"]):not([class*="w-14"]):not([class*="w-16"]) {
  border-radius: var(--aia-radius-lg);
}

/* --- one table type scale --- */
/* Page-level rules set table type at 12, 12.8, 13 and 13.6px. One scale wins. */
html body :is(th, td) { font-size: var(--aia-fs-sm) !important; }
html body th { font-weight: 600; }

/* ---------- 15. Confirmation dialog --------------------------------------
   Destructive actions used the browser's native grey confirm() box on five
   pages and a styled modal on one. This is the single styled dialog; aia.js
   routes the inline handlers through it. */
.aia-confirm-backdrop {
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--aia-sp-4);
  background: rgba(16, 24, 40, .55);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}
.aia-confirm {
  background: var(--aia-surface);
  border-radius: var(--aia-radius-lg);
  box-shadow: var(--aia-shadow-lg);
  width: 100%;
  max-width: 26rem;
  padding: var(--aia-sp-5);
  text-align: center;
  animation: aia-pop .16s ease-out;
}
@keyframes aia-pop { from { transform: scale(.96); opacity: 0 } to { transform: none; opacity: 1 } }
@media (prefers-reduced-motion: reduce) { .aia-confirm { animation: none } }

.aia-confirm__icon {
  width: 3rem; height: 3rem;
  margin: 0 auto var(--aia-sp-3);
  display: grid; place-items: center;
  border-radius: 999px;
  background: var(--aia-danger-soft);
  color: var(--aia-danger);
  font-size: 1.25rem;
}
.aia-confirm__msg {
  margin: 0 0 var(--aia-sp-5);
  font-size: var(--aia-fs-md);
  line-height: 1.5;
  color: var(--aia-text);
  white-space: pre-line;
}
.aia-confirm__actions { display: flex; gap: var(--aia-sp-3); }
.aia-confirm__actions > button {
  flex: 1 1 0;
  min-height: var(--aia-control-h);
  border: 0;
  border-radius: var(--aia-radius);
  font-size: var(--aia-fs-sm);
  font-weight: 600;
  cursor: pointer;
}
.aia-confirm__cancel { background: #eef0f4; color: var(--aia-text); }
.aia-confirm__cancel:hover { background: #e2e6ec; }
.aia-confirm__ok { background: var(--aia-danger); color: #fff; }
.aia-confirm__ok:hover { filter: brightness(.94); }

/* The back-to-top-btn keeps its circle; the control normalisation above
   excluded it from sizing but a radius was still leaking in. */
html body .back-to-top-btn {
  border-radius: 999px !important;
  width: 44px !important;
  height: 44px !important;
  min-height: 0 !important;
  padding: 0 !important;
  font-size: var(--aia-fs-md) !important;
}

/* ==========================================================================
   16. ONE GUTTER
   Measured across every page: the gap between the sidebar and the first
   content card was 44px on 15 pages, 28px on 4, 0 on one, and anywhere from
   37 to 498px on the pages that never adopted a content wrapper. This makes
   it a single token applied the same way everywhere.
   ========================================================================== */
:root { --aia-gutter: clamp(1rem, 0.55rem + 1.25vw, 1.75rem); }

/* The three wrappers in use all get the same padding. */
html body :is(.content-area, .main-content, .content-wrapper) {
  padding: var(--aia-gutter) !important;
}

/* Pages with a sidebar but no wrapper at all: their top-level blocks become
   the content region, so the gutter goes there instead. */
html body.has-app-sidebar:not(:has(.content-area)):not(:has(.main-content)):not(:has(.content-wrapper))
  > *:not(aside):not(.modern-sidebar):not(.aia-topbar):not(.aia-scrim):not(script):not(style):not(link):not(template):not(.aia-confirm-backdrop) {
  padding-left: var(--aia-gutter);
  padding-right: var(--aia-gutter);
}

/* Nothing stacks a second gutter on top of the wrapper's own padding.
   Centred forms (mx-auto) keep their auto margins. */
html body :is(.content-area, .main-content, .content-wrapper)
  > *:not([class*="mx-auto"]):not(.aia-topbar):not(.aia-scrim) {
  margin-left: 0 !important;
  margin-right: 0 !important;
}

@media (max-width: 1024px) {
  /* The mobile rule already zeroes the sidebar offset; keep the side gutter. */
  html body :is(.content-area, .main-content, .content-wrapper) {
    padding: calc(var(--aia-header-h) + var(--aia-sp-3)) var(--aia-gutter) var(--aia-sp-5) !important;
  }
}

/* Many pages nest a `max-w-[1900px] mx-auto p-4` container directly inside the
   wrapper, which added a second 16px gutter on top of the wrapper's own — so
   those pages sat 43px from the sidebar while the rest sat at 27px. Keep the
   centring and the max-width; drop the duplicated side padding. */
html body :is(.content-area, .main-content, .content-wrapper)
  > [class*="max-w-"] {
  padding-left: 0 !important;
  padding-right: 0 !important;
  width: 100%;
}

/* Same again one level deeper, which is how a few of the older pages nest. */
html body :is(.content-area, .main-content, .content-wrapper)
  > * > [class*="max-w-"][class*="mx-auto"] {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* A few pages put the sidebar inside a `flex min-h-screen` row rather than
   using a content wrapper. Padding the row indents the sidebar as well, so the
   gutter goes on the content column instead. */
html body :has(> .modern-sidebar) {
  padding-left: 0 !important;
  padding-right: 0 !important;
}
html body :has(> .modern-sidebar) > *:not(.modern-sidebar):not(.aia-topbar):not(.aia-scrim):not(script):not(style) {
  padding-left: var(--aia-gutter);
  padding-right: var(--aia-gutter);
  flex: 1 1 auto;
  min-width: 0;
}

/* ==========================================================================
   17. FIT
   An element-level pass across all 53 pages (desktop and phone, with modals
   opened) found 82 places where content was wider than its box with no way to
   reach it. They came down to four causes, fixed here rather than per page.
   ========================================================================== */

/* (a) Flex and grid children default to min-width:auto, which refuses to
       shrink below their content. This is the single biggest cause of a row
       pushing past its container. */
html body :is(.flex, .inline-flex, .grid, [class*="grid-cols"]) > * { min-width: 0; }

/* (b) A text input carries an intrinsic width from its `size` attribute
       (~20 characters), so it will not shrink into a narrow column however
       much width:100% it is given. */
html body :is(input, select, textarea) { min-width: 0; }

/* (c) Big display figures and long headings could not wrap, so they ran past
       the edge on a phone. Headings balance; figures break if they must. */
html body :is(h1, h2, h3, .text-3xl, .text-4xl, .text-5xl) { overflow-wrap: break-word; }
html body :is([class*="text-3xl"], [class*="text-4xl"], [class*="text-5xl"]) {
  overflow-wrap: break-word;
  min-width: 0;
}

/* (d) A card given a fixed height clipped its own content. Let cards grow. */
html body :is(.card, .glass-card, [class*="rounded-xl"], [class*="rounded-2xl"])[class*="h-"] {
  min-height: 0;
  height: auto;
}

/* Tables always keep a scroll container, including ones the page already
   wrapped in a div that does not actually scroll. */
html body .aia-table-scroll { overflow-x: auto !important; }
html body :is(.data-table, .table-wrap, .table-container) { overflow-x: auto; }

/* ==========================================================================
   18. FRACTIONAL COLUMNS
   Several pages split the screen with `h-screen flex` and two `w-1/2`
   children. A fractional width is not responsive — it stays at 50% on a
   phone, which squeezed the Company Settings form into 180px and broke its
   labels mid-word. Below the tablet breakpoint these stack full width.
   ========================================================================== */
@media (max-width: 900px) {
  html body :is([class*="w-1/2"], [class*="w-1/3"], [class*="w-2/3"],
                [class*="w-1/4"], [class*="w-3/4"], [class*="w-2/5"], [class*="w-3/5"]) {
    width: 100% !important;
    max-width: 100% !important;
  }

  /* The row itself stacks, and stops being pinned to the viewport height so
     the page scrolls normally instead of trapping two tiny scroll panes. */
  html body .flex:has(> [class*="w-1/"]),
  html body :is(.h-screen, [class*="h-screen"]).flex {
    flex-direction: column;
    height: auto !important;
    min-height: 0 !important;
  }

  /* Those columns often carry their own scroll; let them size to content. */
  html body .flex > [class*="w-1/"][class*="overflow-y-auto"] {
    overflow-y: visible !important;
    height: auto !important;
    max-height: none !important;
  }
}

/* ==========================================================================
   19. TABLES INSIDE SCROLL CONTAINERS
   A table carrying `w-full` inside a horizontally scrolling container shrinks
   to the container instead of overflowing it, so the container never scrolls
   and the cells are crushed — on a phone the Chart of Accounts rendered its
   dates one character per line. Inside a scroller a table must be allowed to
   exceed the box; that is what makes the scroll work.
   ========================================================================== */
html body :is(.aia-table-scroll, .data-table, .table-wrap, .table-container,
               [class*="overflow-x-auto"], [class*="overflow-auto"]) table {
  min-width: max-content !important;
  width: auto !important;
}

/* Cells keep their content on one line so the column widths mean something. */
html body :is(.aia-table-scroll, .data-table, [class*="overflow-x-auto"]) :is(th, td) {
  white-space: nowrap;
}
/* …except genuinely long free text, which may wrap within a sensible width. */
html body :is(.aia-table-scroll, .data-table, [class*="overflow-x-auto"])
  :is(td, th)[class*="description"],
html body :is(.aia-table-scroll, .data-table, [class*="overflow-x-auto"])
  :is(td, th):has(> textarea) {
  white-space: normal;
  min-width: 14rem;
}
