/* ============================================================================
   no-sideways.css — a page never pans sideways on a phone (8 Nov 2026).
   ----------------------------------------------------------------------------
   Cory, from his iPhone on Sage: "Sage scrolls side to side on mobile. I keep
   finding pages with this issue. It must be a global fix!"

   WHY ITS OWN FILE, LINKED BY EVERY PAGE. No shared file reached every page:
   styles.css is missing from 29 pages, nav.js from 47, lore-globals.js from 44.
   A <link> in each <head> works before any script runs, with no flash, on a
   page with no script at all — and test/no-sideways.test.js fails the build if
   a page in public/ goes without it. Rules here must be safe on EVERY page:
   nothing that sets a colour, a font or a size a page might rely on.

   THREE PARTS
     1. The guard: the page itself cannot pan sideways. A safety net only —
        what it hides is cut off, so the real fix is always at the source
        (scripts/no-sideways-sweep.mjs finds it).
     2. Media, embeds, code and tables never outgrow their column.
     3. Long text wraps, and the shared layout primitives let their children
        shrink (min-width: 0 — a flex or grid child otherwise refuses to be
        narrower than its longest word or its widest nowrap line).

   Something that SHOULD scroll sideways (a tab strip, a chip row, a wide
   table) gets its own overflow-x: auto and scrolls inside itself; mark a
   page-sized one with data-hscroll so the sweep knows it is on purpose.

   ?nosideguard=1 on any page switches part 1 off, so the sweep can see the
   causes it would hide: the <link>'s onload sets data-nosideguard on <html>,
   reading the address the page was OPENED with (a page that tidies its own
   address bar keeps the flag).
   ========================================================================== */

/* 1. THE GUARD ─────────────────────────────────────────────────────────────
   clip, not hidden: overflow hidden on <body> makes it a scroll container, and
   every position: sticky inside it stops sticking. clip makes no scroll
   container. Old Safari (< 16) has no clip, so it gets hidden: there it is the
   only way to stop the pan.
   !important because a page's own scroll-unlock (body.style.overflow = 'auto')
   would otherwise switch the guard off from an inline style. Only overflow-x:
   a page's vertical scrolling and its modal locks are untouched. */
@media (max-width: 1024px) {
  html:not([data-nosideguard]),
  html:not([data-nosideguard]) > body { overflow-x: hidden !important; }
  @supports (overflow-x: clip) {
    html:not([data-nosideguard]),
    html:not([data-nosideguard]) > body { overflow-x: clip !important; }
  }
  /* The app shell. A page under nav.js lives in #oi-content (already
     overflow-x: hidden in nav.js) and most scroll their own <main>
     (main.ci-wrap on Sage, main.md on Media…): overflow-y: auto there makes
     overflow-x auto too, and THAT is the pan Cory saw — <body> is
     position: fixed and never moves. A scroller is already a scroll
     container, so clip (it computes to hidden next to overflow-y: auto) costs
     no sticky header anything. data-page-scroll opts in any other page's
     own main column. */
  html:not([data-nosideguard]) #oi-content > main,
  html:not([data-nosideguard]) [data-page-scroll] { overflow-x: hidden; }
  @supports (overflow-x: clip) {
    html:not([data-nosideguard]) #oi-content > main,
    html:not([data-nosideguard]) [data-page-scroll] { overflow-x: clip; }
  }
}

/* 2. NOTHING OUTGROWS ITS COLUMN ───────────────────────────────────────────
   max-width only — a width a page sets still applies up to the column. Tables
   cannot shrink below their content; one that may be wide goes in a
   .oi-table-scroll wrapper, which scrolls inside itself. */
img, video, canvas, iframe, embed, object, table, pre { max-width: 100%; }
pre { overflow-x: auto; }
.oi-table-scroll { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
.oi-table-scroll > table { max-width: none; }

/* 3. LONG TEXT WRAPS; SHARED PRIMITIVES LET THEIR CHILDREN SHRINK ─────────
   Long-text containers get anywhere: unlike break-word it also lowers the
   element's min-content width, which is what lets a flex or grid column narrow
   instead of pushing the page wide. A word breaks only when it cannot fit on a
   line by itself (a pasted URL, an email address).
   Short text — headings, labels, table cells — gets break-word: it still wraps
   a word too long for the line, but it never lets a squeezed flex row or a
   table column shrink a title to a letter a line. */
p, li, dd, blockquote, figcaption { overflow-wrap: anywhere; }
h1, h2, h3, h4, h5, h6, dt, caption, label, legend, td, th,
:is(td, th) :is(p, li, dd, blockquote, figcaption) { overflow-wrap: break-word; }
/* The .lore-* type and card primitives carry the same rules in lore-ui.css —
   a primitive is defined in one place only (test/lore-primitives.test.js). */

/* The shared layout pieces of styles.css and polish.css. :where() keeps this
   at zero specificity, so any page rule still wins. (.lore-seg and .lore-subnav
   are not here on purpose: their buttons keep their width and the strip
   scrolls instead.) */
:where(.card, .empty-state, .oi-comms-row, .oi-action-bar, .oi-sheet, .oi-menu, .oi-dropdown) > * { min-width: 0; }
