/* ==========================================================================
   nx-mobile.css — site-wide mobile correctness layer. ADDITIVE ONLY.
   Loaded LAST so it can correct earlier layers without editing them.

   Fixes shipped here
   ------------------
   1. Wide data tables (Job Queue, retained reports, admin, SOC, manual, …)
      were laid out as 7-8 rigid columns on a phone: every cell wrapped
      mid-word — "neoshieldsecurity.co / m", "ATTEMPT / S", "Cance / l". Many
      of those tables were not inside a scroll wrapper at all, so on top of
      being unreadable they pushed the page horizontally, where
      `html,body{overflow-x:hidden}` silently CLIPPED the right-hand columns
      (including the Action buttons) rather than letting the user reach them.
      Below 720px those tables now stack into labelled cards. Above it they
      scroll inside a container instead of stretching the page.
   2. text-overflow:ellipsis was used without white-space:nowrap in several
      places, so it never took effect and long IDs wrapped instead.
   3. Long unbreakable tokens (job IDs, hashes, hostnames, URLs, header
      values) had no break rule and were the other main overflow source.
   4. Touch targets under the 44px minimum, and side-by-side action buttons
      too narrow to hit.

   Everything is scoped to small viewports or to opt-in classes added by
   assets/js/nx-mobile.js, so desktop rendering is unchanged.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Overflow containment
   -------------------------------------------------------------------------- */

/* Never let a single long token be the thing that widens the page. */
.wrap, .panel, .card, main, article, section, td, th, li, p, dd {
  min-width: 0;
}

/* Long machine strings: break anywhere rather than overflow. */
.mono, code, kbd, samp, .kv, .queue-job-id, .vs-target {
  overflow-wrap: anywhere;
  word-break: break-word;
}

pre, pre code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Ellipsis only works with nowrap — several rules set one without the other. */
.queue-job-id {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Generic scroll shell applied by nx-mobile.js to any unwrapped table. */
.nx-tscroll {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}

/* Existing scroll wrappers were being stretched by their table inside grid
   and flex parents, which defeated the scrolling. */
.nx-tscroll,
.vs-history-scroll,
.table-scroll,
.nx-table-scroll {
  min-width: 0;
}

/* --------------------------------------------------------------------------
   2. Stacked data tables on phones
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {

  /* .nx-stack + data-label are stamped on by assets/js/nx-mobile.js.
     Opt a table out with data-nx-nostack. */
  table.nx-stack {
    display: block;
    width: 100%;
    min-width: 0 !important;   /* beats .queue-table{min-width:920px} etc. */
    border-collapse: separate;
    border-spacing: 0;
  }

  table.nx-stack thead {
    /* Visually hidden, still announced to screen readers via the cell labels. */
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  table.nx-stack tbody,
  table.nx-stack tr,
  table.nx-stack td {
    display: block;
    width: auto;
    min-width: 0;
  }

  table.nx-stack tr {
    border: 1px solid var(--line, #1e2940);
    border-radius: 12px;
    background: var(--panel-2, #0e1420);
    padding: 4px 13px;
    margin: 0 0 11px;
  }

  table.nx-stack tr:last-child { margin-bottom: 0; }

  table.nx-stack td {
    display: grid;
    grid-template-columns: minmax(0, 38%) minmax(0, 1fr);
    gap: 12px;
    align-items: start;
    padding: 9px 0;
    border: 0;
    border-bottom: 1px solid rgba(138, 153, 179, .16);
    font-size: .84rem;
    text-align: left;
  }

  table.nx-stack td:last-child { border-bottom: 0; }

  table.nx-stack td::before {
    content: attr(data-label);
    color: var(--muted, #8a99b3);
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    line-height: 1.45;
    overflow-wrap: anywhere;
  }

  /* Cells with no header text (spacers, action columns) go full width. */
  table.nx-stack td[data-label=""]::before { content: none; }
  table.nx-stack td[data-label=""] { display: block; }

  /* Cells nx-mobile.js deliberately left unlabelled — full-width empty-state
     rows ("No jobs submitted"), group separators — must not get the label
     gutter either, or their text is indented into the value column. */
  table.nx-stack td:not([data-label]) { display: block; text-align: center; }
  table.nx-stack td:not([data-label])::before { content: none; }

  /* The scroll shell has nothing to scroll once the table is stacked. */
  table.nx-stack { overflow: visible; }

  /* Row actions: stack full-width and stay thumb-sized. */
  .queue-actions,
  .nx-stack td form {
    display: block;
    width: 100%;
  }
  .queue-actions .btn,
  .nx-stack td form .btn,
  .nx-stack td form button {
    width: 100%;
    min-height: 44px;
    white-space: nowrap;
  }

  /* Progress bars were pinned wider than the column. */
  .queue-progress { min-width: 0; }
  .queue-progress-track { width: 100%; }

  /* Job ID + timestamp read better as two lines than as a clipped one. */
  .nx-stack .queue-job-id {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    max-width: none;
    overflow-wrap: anywhere;
  }
  .nx-stack .queue-job-id + .faint { display: block; margin-top: 3px; }
}

/* --------------------------------------------------------------------------
   3. Forms, controls and headings on small screens
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* Section heads were flex rows: title and description fought for width. */
  .queue-section-head { flex-direction: column; align-items: flex-start; gap: 4px; }

  /* Any remaining fixed multi-column grid collapses. */
  .form-grid,
  .queue-forms,
  .queue-manual-grid { grid-template-columns: 1fr !important; }
}

@media (max-width: 560px) {
  /* Comfortable, reachable controls. 16px inputs already prevent iOS zoom. */
  .btn, button, [role="button"], summary { min-height: 44px; }
  .btn { padding-block: 11px; }

  /* Buttons that sit in a row go full width rather than shrinking to
     two-character labels. */
  .row .btn, .queue-actions .btn, form .btn[type="submit"] { width: 100%; }

  /* Long headings on narrow screens. */
  h1 { font-size: clamp(1.5rem, 7vw, 2.1rem); overflow-wrap: anywhere; }
  h2 { font-size: clamp(1.2rem, 5.6vw, 1.6rem); overflow-wrap: anywhere; }
  h3 { overflow-wrap: anywhere; }

  /* Breadcrumbs wrapped into an unreadable ladder. */
  .breadcrumbs { font-size: .78rem; overflow-wrap: anywhere; }

  /* Metric tiles: two up is readable, four up is not. */
  .queue-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}

/* --------------------------------------------------------------------------
   4. Respect reduced motion and keep focus visible on touch devices
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

.nx-tscroll:focus-visible { outline: 2px solid var(--accent, #16D9FF); outline-offset: 2px; }

/* ==========================================================================
   5. MOBILE NAVIGATION — burger open state + tap-to-expand accordion
   --------------------------------------------------------------------------
   The drawer's only open mechanism was `.nav-toggle:checked ~ .nav`, driven by
   a <label> pointing at a `display:none` checkbox. When label activation does
   not reach that input (iOS Safari), :checked never matches and the burger
   does nothing — there was no JS fallback, because main.js only observes the
   checkbox and never opens the drawer itself.

   assets/js/nx-nav.js now also sets `.nav-open` on .topbar, so BOTH paths are
   accepted below. The checkbox selector is kept first so the menu still opens
   with JavaScript disabled.

   Second fix: seo-responsive.css force-expanded every group
   (`.nd-menu{display:flex !important}`) and made the headers untappable
   (`.nd-label{pointer-events:none}`) — 67 links in one flat wall, with the
   accordion already implemented in main.js permanently disabled. Groups now
   start collapsed and expand on tap, one at a time.
   ========================================================================== */

@media (max-width: 980px) {

  /* ---- drawer open state -------------------------------------------- */
  .topbar.nav-open .nav {
    max-height: 85vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    opacity: 1;
  }

  /* Burger animates to an X in both the CSS-only and the JS path. */
  .topbar.nav-open .nav-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .topbar.nav-open .nav-burger span:nth-child(2) { opacity: 0; }
  .topbar.nav-open .nav-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  /* Comfortable, unambiguous tap target for the burger itself. */
  .nav-burger { min-width: 44px; min-height: 44px; cursor: pointer; touch-action: manipulation; }

  /* ---- group headers become real controls ---------------------------- */
  /* Lifts seo-responsive.css `.nd-label{pointer-events:none;cursor:default}`,
     which was silently killing main.js's click handler on this element. */
  .nav .nd-label {
    pointer-events: auto;
    cursor: pointer;
    touch-action: manipulation;
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    min-height: 44px;
    padding: 12px 10px;
    border-bottom: 1px solid var(--line, #1e2940);
    color: var(--ink, #e6edf6);
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
  }

  /* Disclosure caret, rotating on open. style.css already draws ::after as a
     triangle; this just makes the state legible in the drawer. */
  .nav .nd-label::after {
    content: "\25BE";
    font-size: .8em;
    opacity: .7;
    transition: transform .18s ease;
  }
  .nav .nd.nd-open > .nd-label::after { transform: rotate(180deg); }
  .nav .nd.nd-open > .nd-label { color: var(--accent, #16D9FF); }

  /* ---- groups collapsed by default, one open at a time --------------- */
  /* !important is required here only because seo-responsive.css declares
     `.nd-menu{display:flex !important}` at this same breakpoint. It also makes
     main.js's inline display styles inert, so the .nd-open CLASS is the single
     source of truth for what is expanded. */
  .nav .nd-menu { display: none !important; }
  .nav .nd.nd-open > .nd-menu {
    display: flex !important;
    flex-direction: column;
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    min-width: 0;
    padding: 4px 0 8px 12px;
    border: 0;
    background: transparent;
    box-shadow: none;
  }

  .nav .nd-menu a {
    min-height: 44px;
    display: flex;
    align-items: center;
    font-size: .95rem;
    padding: 10px 10px;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* Direct links and the CTA keep their own comfortable spacing. */
  .nav > a { min-height: 44px; display: flex; align-items: center; }
}

/* Desktop must be untouched: hover dropdowns, no accordion, no open class. */
@media (min-width: 981px) {
  .topbar.nav-open .nav { max-height: none; opacity: 1; overflow: visible; }
}

/* ==========================================================================
   6. STICKY HEADER
   --------------------------------------------------------------------------
   quantum-defense-os.css:98 already declares
   `.topbar{position:sticky;top:0;z-index:var(--z-nav)}` and that rule wins the
   cascade cleanly at every width — yet the header still scrolled away.

   The cause is two ancestors, not the .topbar rule:

       html { overflow-x: hidden }   nx-system.css
       body { overflow-x: hidden }   seo-responsive.css

   Per CSS spec, when ONE overflow axis is not `visible`, the other computes to
   `auto`. Both html and body therefore became scroll containers, and a sticky
   descendant sticks to its nearest scrolling ancestor — so .topbar was sticking
   to a box that scrolls with the content, i.e. not sticking at all.

   `overflow-x: clip` clips exactly the same way but does NOT create a scroll
   container, so sticky resolves against the viewport again. The `hidden`
   declaration is kept first as a fallback: engines without `clip` support
   discard the second declaration and keep the original behaviour, so nothing
   regresses for them.
   ========================================================================== */

html, body {
  overflow-x: hidden;   /* fallback: pre-Safari-16, pre-Chrome-90 */
  overflow-x: clip;     /* no scroll container -> position:sticky works */
}

.topbar {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: var(--z-nav, 50);
}

/* Anchor targets must not land underneath the pinned bar. */
html { scroll-padding-top: 84px; }

/* The bar sits over page content once pinned, so it needs to be opaque enough
   to read against. Keeps the existing translucent look where backdrop-filter
   is supported, and falls back to a solid panel where it is not. */
.topbar {
  background: var(--color-bg-secondary, #071827);
  border-bottom: 1px solid var(--line, rgba(255, 255, 255, .08));
}

/* Two flat blocks rather than one nested `(a) or (b)` prelude: an @supports
   prelude a browser cannot parse causes the WHOLE block to be dropped, and the
   nested form is not universally parsed. Each condition stands alone here. */
@supports (backdrop-filter: blur(1px)) {
  .topbar {
    background: linear-gradient(180deg, rgba(4, 8, 18, .92), rgba(4, 8, 18, .78));
    backdrop-filter: saturate(140%) blur(12px);
  }
}

@supports (-webkit-backdrop-filter: blur(1px)) {
  .topbar {
    background: linear-gradient(180deg, rgba(4, 8, 18, .92), rgba(4, 8, 18, .78));
    -webkit-backdrop-filter: saturate(140%) blur(12px);
  }
}

/* When the mobile drawer is open the bar owns the screen; cap it to the
   viewport so a long menu scrolls inside the drawer rather than pushing the
   pinned header taller than the screen. */
@media (max-width: 980px) {
  .topbar.nav-open,
  .nav-toggle:checked ~ .nav { max-height: 100dvh; }
  .topbar { max-height: 100dvh; }
}

@media print {
  .topbar { position: static; }
}
