/*!
 * responsive.css — undoes the extension popup's fixed geometry
 * Copyright (c) 2026 Pavel Kotyza <kotyza@gmail.com> — MIT
 *
 * catalog.css is a verbatim copy of the popup's stylesheet, so it hard-codes
 * a 420px body and a fixed-height, overflow:hidden view area — both there to
 * dodge Chrome's extension-popup resize bug, and both wrong on the web.
 * Everything here overrides that. Load AFTER catalog.css.
 */

/* ---- Undo the popup window ------------------------------------------- */
/* ---- App shell: the window is the app, nothing scrolls below the fold ---
   The document never scrolls. The header, tabs and search stay put, and the
   results list is the only scroller. 100dvh (not 100vh) so mobile browser
   chrome collapsing doesn't leave a dead strip at the bottom. */
html { height: 100%; }
body {
  width: auto !important;
  max-width: 720px;
  margin: 0 auto !important;
}
/* Only the catalogue is a viewport-locked shell. Ordinary pages (upload,
   scanner) have content that legitimately runs past the fold and must be
   allowed to scroll - locking them would simply clip them. */
body.app-shell {
  height: 100vh;      /* fallback for browsers without dvh */
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Fixed heights were sized for the popup window; here the view area simply
   takes whatever the chrome above it leaves. min-height:0 is what actually
   lets a flex child shrink enough to give its own child a scrollbar. */
.view-area,
body.axis-has-categories .view-area {
  height: auto !important;
  /* Must be a flex column itself, or the .view inside it is a block that
     grows to its content and the list never gets a scrollbar. */
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden !important;
}
.view { height: auto; min-height: 0; overflow: hidden; }
.view.active { display: flex; flex: 1 1 auto; }

/* The one scroller — on the catalogue. Careful: #results is a *vertical* list
   on index.html but the horizontal card strip (.stripe-track) on fov.html, so
   this must not touch the strip or sideways scrolling dies. */
#results:not(.stripe-track), #fovMapResults {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none !important;
  overflow-y: auto !important;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* no rubber-banding the page behind it */
}

/* ---- Compact chrome (all widths) -------------------------------------
   The popup stacked these vertically because it had a fixed 420px width and
   no height pressure. In a viewport-height shell the height matters more
   than the stacking, at every size. */
.angle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 14px;
  min-height: var(--tap);
}
.angle-label-row { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; margin: 0; }
#angleSlider { flex: 1 1 auto; margin: 0; height: 32px; }

/* Tab labels are authored with a newline for the popup's narrow buttons; on
   one line they cost half the height. */
.view-tabs button { flex-direction: row; gap: 6px; min-height: var(--tap); padding: 0 8px; }
.view-tabs .tab-label { white-space: nowrap; font-size: 12px; }
.view-tabs .tab-icon { width: 16px; height: 16px; }

/* ---- Category row: wrap instead of four-up --------------------------- */
.cat-row {
  flex-wrap: wrap;
  gap: 8px;
}
.cat-row a {
  flex: 0 1 auto;          /* size to the label, not 1/4 of the row */
  min-height: var(--tap);
  padding: 0 12px;
}
.cat-row a span {
  overflow: visible;
  text-overflow: clip;      /* full names now fit; no ellipsis needed */
}

/* ---- Touch targets ---------------------------------------------------- */
.link-row a,
.view-tabs button,
.filter-btn,
.currency-toggle button,
header .header-actions button {
  min-height: var(--tap);
}
header .header-actions button { min-width: var(--tap); }

/* Range thumb is a mouse-sized 14px in the popup. */
#angleSlider { height: var(--tap); }

/* ---- Bottom tab bar on mobile ---------------------------------------- */
.site-nav {
  order: 100;            /* last child of the shell */
  flex: 0 0 auto;
  display: flex;
  background: var(--panel-bg);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.site-nav a {
  flex: 1;
  min-height: var(--nav-h);
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
  text-decoration: none;
  font-size: 12px;
}
.site-nav a[aria-current="page"] {
  color: var(--text);
  box-shadow: inset 0 2px 0 var(--accent);
}

/* ---- Wide phone / small tablet --------------------------------------- */
@media (min-width: 640px) {
  .site-nav {
    order: 0;            /* above the content on wider screens */
    border-top: 0;
    border-bottom: 1px solid var(--border);
    padding-bottom: 0;
  }
  .site-nav a { min-height: 48px; flex: 0 0 auto; padding: 0 20px; }
}

/* ---- Desktop: give the map real room --------------------------------- */
@media (min-width: 1024px) {
  body { max-width: 1000px; }
  #fovMapCanvas { min-height: 420px; }
}

/* Respect a user who asks for less motion. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ---- Category picker (web only) -------------------------------------- */
.cat-pick-btn {
  background: var(--panel-bg);
  color: var(--text);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.cat-pick-btn:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.cat-pick-panel {
  margin: 8px 14px 0;
  padding: 4px;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
}
@media (min-width: 480px) { .cat-pick-panel { grid-template-columns: 1fr 1fr; } }
.cat-pick-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 0 8px;
  font-size: 13px;
  cursor: pointer;
  border-radius: 6px;
}
.cat-pick-row:hover { background: rgba(255, 204, 51, 0.18); }
.cat-pick-row input { width: 18px; height: 18px; accent-color: var(--accent-strong); }

/* ---- Vertical budget on a phone --------------------------------------
   The popup could afford 429px of chrome above the list because it only
   ever showed ~7 rows anyway. On a 812px phone that leaves 6 rows visible.
   Everything below buys that space back. */
@media (max-width: 639px) {
  /* Selector / Products / My Axis are outbound links to axis.com - useful,
     but not worth 44px above the fold on a phone. body is already a flex
     column (catalog.css), so order alone moves them below the list. No
     markup change, and they stay in DOM order for keyboard and screen
     readers reaching them after the content they relate to. */
  .link-row { flex: 0 0 auto; margin: 6px 0 0; }
  .link-row a { font-size: 12px; }
  footer#footerSection { order: 91; flex: 0 0 auto; }

  /* Nothing scrolls past it any more - it is simply always on screen. */
  .search-wrap { padding-top: 6px; padding-bottom: 6px; margin-bottom: 0; }
}

/* ---- Button groups: equal widths, balanced rows -----------------------
   Every group of buttons on the page follows the same rule - equal cells,
   split evenly across rows - so nothing reads as a ragged remainder.

   The link row is three equal outbound links plus the square category
   picker, which is sized to the row height rather than sharing a column. */
.link-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr) var(--tap);
  gap: 8px;
  align-items: stretch;
}
.link-row > a { min-width: 0; }
.cat-pick-btn {
  margin: 0;
  padding: 0;
  width: var(--tap);
  min-width: var(--tap);
  min-height: var(--tap);
  aspect-ratio: 1 / 1;      /* square, per the row height */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
}

/* Two tabs, equal halves. */
.view-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }

/* ---- Chrome budget in the fixed shell --------------------------------
   Every pixel above the list is now permanent, so on a phone the things
   that are not the job move into the existing settings drawer
   (body.axis-advanced-visible, toggled by #advancedBtn). Nothing is
   removed - it is one tap away, where currency and FX rates already live. */
@media (max-width: 639px) {
  /* The link row was hidden here to buy back 44px, but it now carries the
     square category picker - the only way to add shortcuts - so hiding it
     would strand that control in the settings drawer. It stays, and the
     outbound links come along for free since they share the row. */
  body:not(.axis-advanced-visible) .cat-row:not(.has-chips) { display: none; }
}

/* The drawer is taller than the shell, so opening it lets the shell scroll.
   It is a temporary mode, not the reading surface. */
body.app-shell.axis-advanced-visible { overflow-y: auto; }

/* ---- Category chips: equal width, balanced over two rows --------------
   popup.js sets --cat-cols from the chip count: at most four per row, then
   as few rows as that allows, balanced. Every cell is 1fr, so all chips are
   the same width at every row. */
/* popup.js sets --cat-cols so that ordinary grid auto-flow lands on the
   wanted split. Every cell is 1fr, so all chips are one width; a short last
   row simply leaves its trailing cells empty. */
.cat-row.has-chips {
  display: grid;
  grid-template-columns: repeat(var(--cat-cols, 4), 1fr);
  gap: 6px;
}
/* At four-up on a narrow screen the 12px icon plus its gap costs a fifth of
   the label's space; the text is the part that identifies the category. */
@media (max-width: 479px) {
  .cat-row.has-chips a svg { display: none; }
  .cat-row.has-chips a { padding: 0 6px; font-size: 11px; }
}
.cat-row.has-chips a {
  flex: none;
  width: 100%;
  min-width: 0;
  justify-content: center;
}
.cat-row.has-chips a span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- FoV map page ----------------------------------------------------
   fov-map.css was written for a desktop sidebar where a 28px control is
   fine with a mouse. These are the ones a finger has to hit. */
#panel .box-header,
#panel #resetBtn,
#panel .btn-secondary,
#stripeToggle,
#basemapToggle,
#panelToggle {
  min-height: var(--tap);
}
#panel .box-header { display: flex; align-items: center; justify-content: space-between; }
#basemapToggle, #panelToggle { min-width: var(--tap); }

@media (max-width: 639px) {
  /* The map page's title wraps to two lines and steals map height; the
     controls matter more than the full product name on a phone. Scoped to
     .fov-page so it can't quietly restyle the catalogue header too. */
  .fov-page header h1 { font-size: 14px; line-height: 1.2; }
  .fov-page #basemapToggle { font-size: 11px; }
}

/* ---- FoV result cards: no thumbnail on the web -----------------------
   The image came from scraping axis.com product pages, which a page can't
   read cross-origin (see fetchModelImage in fov-map.js). Rather than leave
   every card with an empty grey box, the thumbnail area is removed and the
   cards close up around the text that is actually there. */
.card-thumb { display: none !important; }


/* ---- FoV results strip (fov.html) -------------------------------------
   Horizontal scroller, explicitly restored after the #results rule above. */
.stripe-track {
  overflow-x: auto !important;
  overflow-y: hidden !important;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  /* Deliberately no scroll-snap: the track has 14px of leading padding, so
     the first snap point is 14px in and Home/scrollLeft=0 gets pulled back
     to 14. Free scrolling is also what a sideways card strip wants. */
}
/* A visible track, so it reads as scrollable rather than clipped. */
.stripe-track { scrollbar-width: thin; }
.stripe-track::-webkit-scrollbar { height: 10px; }
.stripe-track::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 5px;
}
.stripe-track::-webkit-scrollbar-thumb:hover { background: var(--muted); }

/* Thumb-sized category chips on a phone: taller than the 44px minimum,
   because these are hit one-handed while walking a site. */
@media (max-width: 479px) {
  .cat-row.has-chips a { min-height: 48px; font-size: 12px; }
}

/* ---- FoV map page on a phone -----------------------------------------
   fov-map.css stacks #layout into a column below 760px, but leaves the map
   with a 240px floor and the panel at flex:0 0 auto / max-height:40vh.
   Neither can shrink, so on a 390x844 phone the column's children total
   578px inside a 461px box and the panel simply paints outside it - the
   results stripe then renders over the "Place the camera" instructions.

   The map keeps a fixed height, the panel takes what is left and scrolls,
   and the stripe is capped so there is something left to take. */
@media (max-width: 760px) {
  #layout { min-height: 0; overflow: hidden; }

  #mapWrap {
    flex: 0 0 auto;
    height: 38vh;
    min-height: 180px;
    max-height: 340px;
  }

  #panel {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;      /* the 40vh cap is what made it overflow */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* 58vh of an 844px phone is 490px - more than half the screen for cards
     that scroll sideways anyway. */
  #resultsStripe { max-height: 34vh; }

  /* The panel is the flexible one, so it must still be worth showing. */
  #panel { min-height: 96px; }
}

/* Short screens (iPhone SE and friends): 38vh + 34vh + the header leaves the
   panel about 20px, so give the map and the stripe less of a small screen
   rather than squeezing the instructions to nothing. */
@media (max-width: 760px) and (max-height: 720px) {
  #mapWrap { height: 30vh; min-height: 150px; }
  #resultsStripe { max-height: 30vh; }
}
