/* ==========================================================================
   Electrical Engineering Fundamentals — mobile layer
   Loaded AFTER site.css on every page.
   --------------------------------------------------------------------------
   ABSOLUTE RULE: every declaration in this file lives inside a @media block
   with a max-width condition. There is not a single top-level selector, so
   this file is structurally incapable of moving the desktop rendering.

   Breakpoints:  900px tablet · 640px phone · 400px small phone

   What the rest of the site already handles, and is NOT restated here:
     site.css   860px .split · 640px wrap padding, .ex-card, .stats,
                .brand-sub · 560px .canvas scrolls instead of shrinking
     chat.html  900px sidebar becomes a drawer · 640px .chat-starters and the
                user bubble go full width
     admin.js   the users table carries min-width:660px inside
                #usersBox{overflow-x:auto}, so it already scrolls in its own box
   Everything below is what those leave broken on a phone.

   A few rules have to out-specify a page-local <style> block: login.html and
   admin.html load their own <style> AFTER this file, and chat.html sizes its
   composer by id. Where that happens it is called out in the comment.
   ========================================================================== */


/* ==========================================================================
   TABLET — 900px and below
   ========================================================================== */
@media (max-width: 900px) {

  /* The page itself must never scroll sideways: anything that still overflows
     is clipped rather than dragging the topbar and footer off-screen with it.
     `clip` creates no scroll container, so the sticky .topbar keeps working
     and chat.html's overflow:hidden app shell is unaffected; `hidden` is the
     fallback for engines without overflow:clip. */
  body { overflow-x: hidden; overflow-x: clip; }

  /* .topbar — "Electrical Engineering Fundamentals" is 35 characters and is
     the first thing to give. Let the brand shrink and ellipsis instead of
     pushing the nav and the theme button past the right edge. */
  .brand { min-width: 0; }
  .brand > span {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* chat.html — the delete-conversation button is opacity:0 until :hover or
     :focus-within. A touch screen has no hover, so on a phone it is invisible
     and there is no other way to delete a conversation. Show it, and give it
     a real target: the row measures 58px, so 44px costs no height. */
  .conv-del { opacity: 1; width: 44px; height: 44px; }

  /* chat.html is the one page with viewport-fit=cover, so env() is live here.
     The conversation drawer is position:fixed to the bottom of the screen and
     the sign-out button sits directly under the iOS home indicator. */
  .chat-side-foot { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }

  /* The chat shell is a 100dvh flex column — topbar, transcript, composer,
     footer — so the FOOTER, not the composer, is the element the home
     indicator covers. env() is 0px on every device without an inset, so this
     changes nothing elsewhere. */
  .chat-page footer.site { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}


/* ==========================================================================
   PHONE — 640px and below
   ========================================================================== */
@media (max-width: 640px) {

  /* ---- topbar ------------------------------------------------------------
     At 375px the wordmark (~245px), the nav and the 44px theme button add up
     to far more than the 343px available — on chat.html there is a hamburger
     in front of it as well. Truncating the wordmark leaves "El…", which is
     worse than useless, so on phones the gold mark alone is the home link and
     the name moves to the accessibility tree: same treatment as .sr, so it
     stays in the DOM and still gives the link its accessible name.
     Budget after this, on index.html: 26 + 12 + 216 + 12 + 44 = 310 of 343. */
  .brand > span {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
  /* With the wordmark gone the home link is just the 26px mark, which is
     under the minimum on its own. The spacer absorbs the extra width, so the
     mark does not move. */
  .brand { min-width: 44px; min-height: 44px; }
  .topbar-in { gap: 12px; }
  .topnav { flex: none; gap: 2px; }
  .topnav a {
    display: inline-flex; align-items: center; min-height: 44px;
    padding: 6px 8px; white-space: nowrap;
  }
  .icon-btn { width: 44px; height: 44px; }

  /* ---- tap targets: 44px minimum on anything you press -------------------
     .btn is already 46px; .toggle and .ex-card are taller still. These are
     the ones that come up short. */
  .btn-sm { min-height: 44px; }
  .opt { min-height: 44px; }
  .backlink { min-height: 44px; }
  details.reveal summary { min-height: 44px; }
  input[type="range"] { min-height: 44px; }

  /* Any text field under 16px makes iOS Safari zoom the page on focus, and it
     does not zoom back out — the layout is then wider than the screen for the
     rest of the session. site.css uses 15px (14px for .mono), and login.html
     and admin.html restate 15px for their email/password fields in a <style>
     that loads after this file, so the leading `body` is there to win the
     specificity tie rather than to select anything. */
  body input[type="text"], body input[type="number"], body input[type="email"],
  body input[type="password"], body input[type="search"], body input.mono,
  body select, body textarea { font-size: 16px; }

  /* chat.html sizes the composer by id, which no selector above can reach.
     This is the worst instance of the zoom trap: the shell is height:100dvh
     with overflow:hidden, so a user who zooms in by tapping the composer
     cannot scroll back to what is now off-screen. */
  #chatInput { font-size: 16px; }

  /* ---- grid tracks wider than the box they sit in ------------------------
     auto-fit guarantees one track, not that the track fits: if its floor is
     wider than the container the grid overflows. Measured on ch1's "What you
     need before you start" panel: .grid-2 (floor 320px) lays a 320px track in
     a 301px box at 375px, spilling 18px through the panel's right edge — and
     at 360px and below it clears the viewport too and takes the whole document
     sideways (357px of scrollWidth at a 320px viewport).
     min(100%, …) keeps the identical multi-column layout wherever it fits. */
  .grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
  .grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }

  /* ---- let site.css's "scroll the schematic" rule actually take effect ---
     site.css gives .canvas overflow-x:auto and its svg min-width:470px below
     560px, so a circuit scrolls instead of shrinking. On the bench layouts
     that never happened: .bench and .bench-controls are grids, a grid item's
     automatic minimum size is its min-content width, and the 470px svg made
     that 530px — so the track grew to 530px, the .canvas was 488px wide, and
     it never had anything to scroll. The page went to 546px of scrollWidth at
     a 375px viewport on six of the eight exercises. Releasing the automatic
     minimum lets the track be 303px and hands the overflow back to .canvas,
     which is where site.css meant it to go. */
  .bench > *, .bench-controls > *, .split > * { min-width: 0; }

  /* ---- readouts sized for a full-width desktop column --------------------
     site.css locks .stats to two columns at this width. Inside a
     .bench-controls card on a ~600px screen those columns are ~119px wide,
     and "−123.45" plus its unit at 30px is ~119px before the tile's padding. */
  .stat .v { font-size: 25px; }

  /* Same on the multimeter: at 32px a signed four-figure reading and its unit
     overrun the screen bezel in a two-up bench card. */
  .dmm-screen { font-size: 28px; padding: 12px 14px; }
  .dmm-unit { font-size: 15px; }

  /* ---- option buttons ----------------------------------------------------
     A grid item's automatic minimum is its min-content width, so one long
     word in an .opts-inline cell pushes the button out of its track. */
  .opt { min-width: 0; overflow-wrap: anywhere; }

  /* ---- charts ------------------------------------------------------------
     EEF.linePlot draws into a 560px viewBox, and both callers — ch1's q(t)/i(t)
     plots and render.js's plot() block — host it in a plain div, so unlike
     .canvas it is not covered by the 560px rule in site.css. Squeezed into a
     303px column its 11px axis labels render at 6.7px. Same remedy the design
     already chose for schematics: scroll it rather than shrink it, at the same
     470px floor. */
  .chart-host { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .chart-host > svg { min-width: 470px; }

  /* ---- exercise stage header --------------------------------------------
     .stage-head already wraps; the flex:1 spacer then lands alone on a new
     line as an empty full-width row, adding a 16px gap of dead space above
     the reference and the badge. */
  .stage-head { gap: 12px; }
  .stage-head .spacer { display: none; }

  /* ---- footer ------------------------------------------------------------
     32px between stacked blocks reads as a hole in the page, and a long
     unbroken string (a URL, an account email) must not set the flex item's
     minimum width. chat.html's compact app-shell footer is more specific and
     keeps its own spacing. */
  .fgrid { gap: 20px; }
  .fgrid > * { min-width: 0; }

  /* ---- toast -------------------------------------------------------------
     Centred on a 50% offset with no width limit, a long message overflows
     both edges. Pin it to the gutters instead and clear the home indicator.
     .toast.on has to be restated because it also sets transform. */
  .toast {
    left: 16px; right: 16px;
    bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    transform: translateY(16px);
    justify-content: center; text-align: center;
  }
  .toast.on { transform: translateY(0); }

  /* ---- chat.html in landscape -------------------------------------------
     With viewport-fit=cover the notch eats one side of a landscape phone.
     These three are the page's gutters and are all 16px at this width, so
     max() is a no-op in portrait where the insets are 0. */
  .chat-page .wrap, .chat-page .chat-col, .chat-page .chat-composer-in {
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
  }

  /* render.js gives model equations overflow-x:auto so a long one scrolls
     instead of overflowing. But .eqblock is text-align:center, and a scroll
     box starts at its left edge — centred content wider than the box spills
     equally both ways and the left half can never be scrolled to. Chat is the
     only place the content length is not known in advance; ch1's own centred
     equation blocks are untouched. */
  .chat-block .eqblock { text-align: left; }
}


/* ==========================================================================
   SMALL PHONE — 400px and below
   ========================================================================== */
@media (max-width: 400px) {

  /* ---- topbar: buy back the last few pixels -----------------------------
     Tighten the bar's own gutter and gaps only, never the page gutter.
     Measured on index.html, the widest nav on the site (three links): at 320px
     the phone budget above overruns by 8px and pushes the theme button off the
     edge, so this claws back 16px — 6 from the bar's gaps, 6 from the link
     padding, 4 from the gaps between the links. */
  .topbar .wrap { padding: 0 12px; }
  .topbar-in { gap: 6px; }
  .topnav { gap: 0; }
  .topnav a { font-size: 13px; padding: 6px 4px; }

  /* index.html now carries a FOURTH link ("Chat"), which overruns even the
     budget above and clips the theme toggle at the right edge. Rather than hide
     a link, let the nav scroll within itself and pin the toggle: every
     destination stays reachable and nothing is pushed off-screen. The
     scrollbar is hidden because the bar is only 60px tall.

     The `flex: 1 1 auto` is load-bearing: the 640px block above sets
     `.topnav { flex: none }`, which pins the nav at its content width and
     stops min-width/overflow from ever taking effect. */
  .topnav {
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .topnav::-webkit-scrollbar { display: none; }
  .icon-btn { flex: none; }

  /* ---- the remaining fixed grid floors -----------------------------------
     Same min(100%, …) treatment as .grid-2/.grid-3, for the tracks whose
     floors only exceed their container on the narrowest phones:
     .bench-controls 260px (used by ch1's benches and admin's limits panel),
     .answer-grid 140px, .opts-inline 96px. Identical layout wherever the
     space is there. */
  .bench-controls { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
  .answer-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr)); }
  .opts-inline { grid-template-columns: repeat(auto-fit, minmax(min(100%, 96px), 1fr)); }

  /* .stats stays two-up, so its columns are ~115px inside a panel here and
     25px still overflows a three-figure reading with its unit. */
  .stat .v { font-size: 22px; }
  .dmm-screen { font-size: 24px; }
  .dmm-unit { font-size: 13px; }

  /* ---- hero -------------------------------------------------------------
     The two hero buttons total ~342px and wrap to a ragged second row of one.
     Stack them full width — they are the page's primary action and now read
     as one thing. */
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn { width: 100%; }

  /* index.html "The source text" card: its inner column carries an inline
     min-width:280px, 36px wider than the card's content box at 320px. An
     inline style can only be reached with !important. */
  #book .card > div { min-width: 0 !important; }

  /* Model follow-up suggestions are a grid with an inline
     minmax(230px, 1fr) — 14px wider than the chat body at 320px, so the
     arrow on each card is clipped. Inline again, so !important again. */
  .chat-suggest > .grid { grid-template-columns: minmax(0, 1fr) !important; }
}
