/* ==========================================================================
   Floating dock (UI-1, 2026-10-26) - one home for every site-wide floating widget
   --------------------------------------------------------------------------
   templates/base.html renders ONE fixed bottom-right container, #jtp-float-dock,
   holding (left to right) the route cheatsheet pill, when the page has one, and
   the site chat launcher (the unchanged partials/chatbot_widget.html). Before
   this, both were independently `position: fixed` in the same corner and sat
   on top of each other and on top of page controls.

   Loaded from base.html through versioned_url_for (served from the image).
   static/css/chatbot.css is NOT edited: the launcher and window are overridden
   here with #jtp-float-dock-scoped selectors, which outrank its class rules.

   Geometry contract (only while the dock renders: body.has-float-dock):
     --jtp-dock-offset   gap between the dock and the viewport edge
     --jtp-dock-height   tallest widget (the 56px chat launcher)
     --jtp-dock-reserve  offset + safe area + height + 0.5rem: the band a
                         full-screen player keeps free at its bottom
     --jtp-dock-lift     written on :root by static/js/float-dock.js while a
                         [data-dock-avoid] bar (or the cookie banner) is
                         visible under the dock; 0px otherwise
   Every var() below carries a fallback, so a missing token never makes a
   calc() invalid.

   The dock MUST NOT get transform, filter, backdrop-filter, perspective,
   contain or will-change: any of them would re-anchor the position:fixed chat
   window to the dock instead of the viewport (tests/test_float_dock.py).
   ========================================================================== */

body.has-float-dock {
  --jtp-dock-offset: 1rem;
  --jtp-dock-height: 56px;
  --jtp-dock-reserve: calc(var(--jtp-dock-offset, 1rem) + env(safe-area-inset-bottom, 0px) + var(--jtp-dock-height, 56px) + 0.5rem);
}

@media (max-width: 768px) {
  body.has-float-dock {
    --jtp-dock-offset: 0.75rem;
  }
}

/* --- The dock -------------------------------------------------------------- */
#jtp-float-dock {
  position: fixed;
  right: calc(var(--jtp-dock-offset, 1rem) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--jtp-dock-offset, 1rem) + env(safe-area-inset-bottom, 0px) + var(--jtp-dock-lift, 0px));
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  max-width: calc(100vw - 2 * var(--jtp-dock-offset, 1rem));
  /* The gap between the widgets is not a click target. */
  pointer-events: none;
  transition: bottom 0.2s ease;
}

#jtp-float-dock > * {
  pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
  #jtp-float-dock {
    transition: none;
  }
}

@media print {
  #jtp-float-dock {
    display: none !important;
  }
}

/* --- Cheatsheet pill ------------------------------------------------------- */
#jtp-float-dock .route-cheatsheet-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex: 0 1 auto;
  min-width: 0;
  min-height: 44px;
  box-sizing: border-box;
  padding: 0.85rem 1.1rem;
  border-radius: 999px;
  background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
  color: #f8fafc;
  border: 1px solid rgba(148, 163, 184, 0.35);
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.28);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.2;
  white-space: nowrap;
}

#jtp-float-dock .route-cheatsheet-link:hover {
  transform: translateY(-1px);
  color: #ffffff;
  border-color: rgba(96, 165, 250, 0.55);
  box-shadow: 0 16px 32px rgba(15, 23, 42, 0.36);
}

#jtp-float-dock .route-cheatsheet-icon {
  flex: 0 0 auto;
  width: 1.55rem;
  height: 1.55rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: rgba(59, 130, 246, 0.2);
  font-size: 0.9rem;
}

/* A label longer than the room left beside the launcher is truncated, never
   pushed off-screen; the full text stays in the accessible name. */
#jtp-float-dock .route-cheatsheet-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The ring sits outside the control, on the page: blue-600 on the light page
   (5.2:1 on white), blue-300 on the dark page. */
#jtp-float-dock .route-cheatsheet-link:focus-visible,
#jtp-float-dock .chatbot-trigger:focus-visible {
  outline: 3px solid #2563eb;
  outline-offset: 3px;
}

html[data-theme="dark"] #jtp-float-dock .route-cheatsheet-link:focus-visible,
html[data-theme="dark"] #jtp-float-dock .chatbot-trigger:focus-visible {
  outline-color: #93c5fd;
}

/* Narrow phones: the pill becomes a 44px icon button. The label stays in the
   DOM, visually hidden, so the accessible name still starts with the visible
   wording of the wider layouts (WCAG 2.5.3). */
@media (max-width: 374px) {
  #jtp-float-dock .route-cheatsheet-link {
    width: 44px;
    height: 44px;
    padding: 0;
    gap: 0;
    justify-content: center;
    flex: 0 0 auto;
  }

  #jtp-float-dock .route-cheatsheet-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
}

/* --- Chat launcher + window (overrides static/css/chatbot.css) ------------- */
#jtp-float-dock #chatbot-container {
  flex: 0 0 auto;
}

#jtp-float-dock .chatbot-trigger {
  position: relative;
  right: auto;
  bottom: auto;
  z-index: auto;
  width: var(--jtp-dock-height, 56px);
  height: var(--jtp-dock-height, 56px);
  box-sizing: border-box;
  flex: 0 0 auto;
  /* chatbot.css animates `all`; inside the dock only the hover / open effects
     animate, never the launcher's geometry */
  transition: transform 0.3s, background-color 0.3s;
}

/* The hover label opens upward, not leftward over the pill. */
#jtp-float-dock .chatbot-trigger::after {
  top: auto;
  right: 0;
  bottom: calc(100% + 0.5rem);
  margin: 0;
  transform: none;
}

/* The window stays position:fixed (to the viewport) and opens above the
   launcher; it follows the lift and always fits the viewport. */
#jtp-float-dock .chatbot-window {
  right: calc(var(--jtp-dock-offset, 1rem) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--jtp-dock-offset, 1rem) + env(safe-area-inset-bottom, 0px) + var(--jtp-dock-lift, 0px) + var(--jtp-dock-height, 56px) + 0.75rem);
  width: min(24rem, calc(100vw - 2rem));
  height: min(32rem, calc(100vh - 10rem - var(--jtp-dock-lift, 0px)));
  height: min(32rem, calc(100dvh - 10rem - var(--jtp-dock-lift, 0px)));
}

/* Phones and small tablets (UI-1.1 D1): the open window must never sit under the
   top-left "Menu" pill (fixed, top 76px, lower edge about 114px from the top). On the
   course players that pill is raised to z-index 10000 !important (course_player.css),
   above the dock (9999), and painted over the window's title.
   1. Height: the window's top stays at about 124px (12.75rem = the window's bottom
      offset of 5rem plus 7.75rem of room for the header and the pill), whatever the
      lift. On a short viewport it keeps a usable floor of 15rem, but never grows
      past the viewport's top edge (the floor itself is capped at the room above the
      launcher less 0.5rem). Trade-off: only in that short-viewport case (100dvh
      minus the lift below 27.75rem / 444px, e.g. a landscape phone, or a 640px-tall
      phone under the cookie banner) does the window reach above 124px; while it is
      open it then covers the pill (item 2 keeps the pill below it) and, on a
      landscape phone, the right end of the site header - the visitor closes it to
      get them back. Before, the window shrank instead, down to a 91px sliver.
   2. Stacking, on the course players only (the pages with .course-player-wrapper,
      the only ones that load course_player.css): while the window is open the pill
      drops below the dock (9998). Elsewhere the pill keeps its own z-index (999),
      below the sticky header (1000) and its menus, so it is not touched there.
   3. An open header menu (the language menu, the search panel) beats everything
      else at the top of the page, on every page up to 768px: while one is open the
      header (1000; 9998 on the players) rises to 10001, above the pill (999; 10000
      on the players) and above the dock (9999) with the open chat window, so neither
      covers the menu. Closing the menu restores it.
   UI-1.1 adds exactly two !important declarations, each to beat one in
   course_player.css:
     - the pill's 9998 (rule 2) beats `.sidebar-reopen-btn { z-index: 10000
       !important }` (course_player.css:287-289): id + :has() specificity;
     - the header's 10001 (rule 3) beats `.main-header { z-index: 9998 !important }`
       (course_player.css:292-294): :has() + class specificity.
   Browsers without :has() keep only the height rule. */
@media (max-width: 768px) {
  #jtp-float-dock .chatbot-window {
    height: min(32rem, max(calc(100vh - 12.75rem - var(--jtp-dock-lift, 0px) - env(safe-area-inset-bottom, 0px)),
                           min(15rem, calc(100vh - 5.5rem - var(--jtp-dock-lift, 0px) - env(safe-area-inset-bottom, 0px)))));
    height: min(32rem, max(calc(100dvh - 12.75rem - var(--jtp-dock-lift, 0px) - env(safe-area-inset-bottom, 0px)),
                           min(15rem, calc(100dvh - 5.5rem - var(--jtp-dock-lift, 0px) - env(safe-area-inset-bottom, 0px)))));
  }

  body:has(#chatbot-window.active) .app-layout:has(.course-player-wrapper) > #sidebar-reopen-btn {
    z-index: 9998 !important;
  }

  body:has(#lang-selector[open], #search-dropdown.active) .main-header {
    z-index: 10001 !important;
  }
}

/* --- Normal pages: bottom gutter (AC2) ------------------------------------ */
/* A spacer, not padding: about 50 pages force `.main-content { padding: 0
   !important }`, which would zero a padding-bottom. At scroll end the last
   controls and footer links clear the dock. */
body.has-float-dock .main-content::after {
  content: "";
  display: block;
  height: calc(var(--jtp-dock-height, 56px) + 1.5rem);
}

/* The site footer follows .main-content, so its last line (the centred copyright)
   needs the same room at the end; inside the footer, painted by its own background. */
body.has-float-dock .main-footer::after {
  content: "";
  display: block;
  height: calc(var(--jtp-dock-height, 56px) + 0.5rem);
}

/* While the dock is lifted above a FIXED bar (a simulator's bottom bar, the cookie
   banner), the document gets that much more room at its very end, so the footer's
   last links still scroll clear of the bar and the lifted dock. Sticky bars take
   their own space in the flow and are excluded (--jtp-dock-lift-fixed), so the
   spacer can never feed back into the lift. 0px when nothing lifts the dock. */
body.has-float-dock::after {
  content: "";
  display: block;
  height: var(--jtp-dock-lift-fixed, 0px);
}

/* --- Full-screen players: keep the dock's band free (AC2, D3/A2/A4) -------- */
/* Every position:fixed full-screen wrapper (top 60/70px, bottom 0) ends its
   content box above the dock: the reserved band is painted by the wrapper's
   own background, so the iframe / player chrome never runs under the dock,
   and the band grows with the lift. ONE central list, because the per-page
   sheets (course_player.css) are not loaded on maths, statistics, bookkeeping
   or PMP pages. tests/test_float_dock.py fails when a template adds a new
   full-screen wrapper that is missing here. The PMP pages reuse generic class
   names, so those four are matched only with their PMP trademark notice child
   (inside :is(), a browser without :has() drops just those entries). */
@media screen {
  body.has-float-dock :is(
    .course-player-wrapper,
    .cert-course-wrapper,
    .sql-intro,
    .stats-course-wrapper,
    .math-player-wrapper,
    .math-module-wrapper,
    .math-page-wrapper,
    .bk-page-wrapper,
    .bk-module-page,
    .bk-test-page,
    .bk-results-page,
    .bk-simulator,
    .bk-cert-page,
    .bk-error-page,
    .norwegian-player-wrapper,
    .french-player-wrapper,
    .german-player-wrapper,
    .ielts-player-wrapper,
    .spanish-player-wrapper,
    .spanish-module-wrapper,
    .spanish-lesson-wrapper,
    .spanish-exam-run-wrapper,
    .pmp-player-wrapper,
    .pmp-page-wrapper,
    .cert-page-wrapper,
    .module-wrapper:has(> .pmp-trademark-notice),
    .results-wrapper:has(> .pmp-trademark-notice),
    .simulator-wrapper:has(> .pmp-trademark-notice),
    .test-wrapper:has(> .pmp-trademark-notice)
  ) {
    box-sizing: border-box;
    padding-bottom: calc(var(--jtp-dock-reserve, 0px) + var(--jtp-dock-lift, 0px)) !important;
  }

  /* (UI-1.1 rework 1) Where the course iframe is a flex item under the course header
     (AWS SAA), its automatic minimum height is the iframe's intrinsic 150px: on a short
     phone under the cookie banner the header left less than that, and the iframe ran
     past the content box into the dock's band (4px at 360x640 with the Inter web font).
     It may now shrink; nothing changes where it has room. */
  body.has-float-dock .course-player-wrapper .course-iframe {
    min-height: 0;
  }
}

/* --- Menu-pill clearance on native player headers (D4) --------------------- */
/* The global "Menu" reopen pill (.sidebar-reopen-btn: fixed, top 84px / 76px, left
   16px / 12px, about 90px wide) shows whenever the main sidebar is collapsed and
   covered the back button / breadcrumb at the left end of these headers. The header
   content now starts to the right of the pill; the pill itself is unchanged. The
   iframe course players' .course-header is handled in course_player.css (loaded only
   there); these native pages do not load that sheet, hence one list here. PMP's
   generic .module-header is matched through its trademark-notice sibling. */
/* Wider screens only, every one of them: a fixed 7.5rem inset on a phone cut header
   text off at the right edge, pushed timers off-screen and made headers far taller.
   Phones get the targeted rules further down instead (row-1 layouts, a top padding
   or a back-button margin), and only where the pill actually covered a control. */
@media (min-width: 769px) {
  .app-layout.sidebar-collapsed :is(
    .simulator-header > .header-content,
    .listening-header,
    .spanish-course-header,
    .norwegian-course-header,
    .german-course-header,
    .french-course-header,
    .ielts-course-header,
    .spanish-lesson-header,
    .math-header,
    .bk-test-header,
    .bk-module-page > .bk-module-header,
    .bk-exam-header,
    .pmp-trademark-notice ~ .module-header
  ) {
    padding-left: 7.5rem;
  }
}

/* ... and on phones / small tablets, where they wrap anyway, the right group
   takes the first row (right-aligned, beside the pill) and the back button and
   title start the second row at the page's normal inset, full width. (The maths
   module's right group can be empty, so it keeps the inset at every width; French
   hides its right group on phones, so there only the back button moves right of
   the pill and the long title wraps to its own full-width row.) */
@media (max-width: 768px) {
  .app-layout.sidebar-collapsed :is(
    .spanish-course-header,
    .norwegian-course-header,
    .german-course-header,
    .ielts-course-header
  ) {
    flex-wrap: wrap;
    row-gap: 0.75rem;
  }

  .app-layout.sidebar-collapsed :is(
    .spanish-course-header > .spanish-header-right,
    .norwegian-course-header > .norwegian-header-right,
    .german-course-header > .german-header-right,
    .ielts-course-header > .ielts-header-right
  ) {
    order: -1;
    width: 100%;
    flex: 0 0 auto;
    align-self: stretch;
    justify-content: flex-end;
    flex-wrap: wrap;
    box-sizing: border-box;
    /* its own items stay right of the pill too (pill: left 12px, about 90px wide) */
    padding-left: 6rem;
  }

  /* Spanish's right group is a plain block around one link. */
  .app-layout.sidebar-collapsed .spanish-course-header > .spanish-header-right {
    display: flex;
  }

  .app-layout.sidebar-collapsed .french-course-header .french-header-left {
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }

  .app-layout.sidebar-collapsed .french-course-header .french-back-btn {
    margin-left: 6.5rem;
  }

  /* Where a header stacks and centres a row, that row would overflow to both
     sides and slide back under the pill: let it wrap instead. */
  .app-layout.sidebar-collapsed .norwegian-header-left {
    flex-wrap: wrap;
    min-width: 0;
  }

  /* Simulators WITH a right group (German / French listening: task dots + timer;
     the header already stacks on phones): the right group takes row 1 beside the
     pill, the back button and title follow - same height as before. */
  .app-layout.sidebar-collapsed .simulator-header > .header-content > .header-right {
    order: -1;
    width: 100%;
    align-self: stretch;
    justify-content: flex-end;
    flex-wrap: wrap;
    box-sizing: border-box;
    padding-left: 6rem;
  }

  /* Simulators WITHOUT a right group (German / French reading, writing, speaking:
     back button, badge, title and timer share one row). Their items join one
     wrapping row; the back button starts right of the pill and the timer keeps to
     the right edge, so nothing is pushed off-screen. */
  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    column-gap: 1rem;
    row-gap: 0;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) > .header-left {
    display: contents;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) .back-btn {
    margin-left: 5.5rem;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) > :is(.timer-display, .timer-container) {
    margin-left: auto;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) .exam-title {
    min-width: 0;
  }

  /* IELTS listening: the section + timer group takes row 1 beside the pill, the
     exit button and title row 2; a slightly narrower inset and a timer box that
     may shrink keep both on one line down to 360px. */
  .app-layout.sidebar-collapsed .listening-header {
    flex-wrap: wrap;
    row-gap: 0.5rem;
    padding-left: 1rem;
    padding-right: 1rem;
  }

  /* nowrap: the section label shrinks onto two lines instead of pushing the
     timer onto a line of its own */
  .app-layout.sidebar-collapsed .listening-header > .listening-timer {
    order: -1;
    width: 100%;
    justify-content: flex-end;
    flex-wrap: nowrap;
    gap: 0.5rem;
    box-sizing: border-box;
    padding-left: 4.75rem;
  }

  .app-layout.sidebar-collapsed .listening-header .listening-timer-display {
    min-width: 0;
  }

  /* Bookkeeping test / module pages: their first row is a breadcrumb that started
     under the pill's lower edge (about 114px from the top); start it just below
     instead (the headers begin at 70px). Nothing moves sideways. */
  .app-layout.sidebar-collapsed :is(.bk-test-header, .bk-module-page > .bk-module-header) {
    padding-top: 3rem;
  }

  /* Maths module: only the back button moves right of the pill. */
  .app-layout.sidebar-collapsed .math-header .back-btn {
    margin-left: 5.5rem;
  }

  /* (Spanish lesson, PMP module and bookkeeping exam headers: the pill covers
     nothing there on phones, so they keep their original layout.) */
}

/* Phones: the reading / writing / speaking simulators break after the back button
   and the timer, so the timer sits in row 1 beside the pill and the badge and
   title share row 2 (the title wraps inside it). */
@media (max-width: 640px) {
  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) > :is(.timer-display, .timer-container) {
    order: 1;
  }

  /* a slimmer timer box keeps row 1 as tall as the back button */
  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) .timer-display {
    padding: 6px 16px;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right))::after {
    content: "";
    order: 2;
    flex: 0 0 100%;
    height: 0;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) > .header-left > :not(.back-btn) {
    order: 3;
    margin-top: 0.125rem;
  }

  .app-layout.sidebar-collapsed .simulator-header > .header-content:not(:has(> .header-right)) .exam-title {
    flex: 1 1 0;
  }

  /* Maths module on phones: the back button (one line) stays beside the pill and the
     module title takes its own full-width row, instead of being squeezed beside it. */
  .app-layout.sidebar-collapsed .math-header .header-left {
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }

  .app-layout.sidebar-collapsed .math-header .back-btn {
    white-space: nowrap;
  }

  .app-layout.sidebar-collapsed .math-header .module-title {
    flex: 1 1 100%;
  }

  /* IELTS listening: its header gained a row on phones; win back the height in its
     vertical padding (the timer row still clears the pill sideways). */
  .app-layout.sidebar-collapsed .listening-header {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
  }
}

/* Phones (pill at top 76px, lower edge about 114px from the top): normal-flow
   pages whose first line is a breadcrumb or back link started just under the
   pill's lower edge. Move that first line down; nothing moves sideways. */
@media (max-width: 600px) {
  .app-layout.sidebar-collapsed .site-crumb {
    padding-top: 1rem;
  }
  .app-layout.sidebar-collapsed .test-container > .back-link {
    margin-top: 1rem;
  }
}

/* --- English site header on phones (UI-1.1 D2) ------------------------------ */
/* Below 601px the English header was wider than the phone: logo + language button
   (two flags and a caret, 84px) + five icon buttons + "Sign In", with 8px / 16px gaps,
   needed 456px. At 390px it stuck out 66-68px, at 360px 96-99px, and Android Chrome
   then widened the layout viewport, so the fixed dock and the cookie banner were
   anchored partly off-screen. (The Norwegian header has its own compaction, inline in
   base.html; these rules leave it alone: html:not([lang="nb"]). Only the menu
   placement further down applies to every locale.)
   Nothing is hidden: every header action stays in the header, only tighter - smaller
   gaps and padding, 32px icon buttons (28px below 390px; still above the 24px target
   minimum), the language button keeps both flags at a smaller size and drops only
   its decorative caret, and "Sign In" stays on one line with less padding. The 40px
   logo is unchanged, and the header is one 57px row again (signed in and in Norwegian
   it already was; "Sign In" used to wrap onto two lines and make it 73px tall).
   Measured: the header needs 348px of 360px and 372px of 390px (12px / 18px to spare). */
@media (max-width: 600px) {
  html:not([lang="nb"]) .main-header .header-container {
    gap: 0.5rem;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  html:not([lang="nb"]) .main-header .logo-link {
    flex: 0 0 auto;
  }

  html:not([lang="nb"]) .main-header .header-actions {
    gap: 0.25rem;
    min-width: 0;
  }

  html:not([lang="nb"]) .main-header .header-actions .icon-btn:not(.lang-summary) {
    flex: 0 0 auto;
    width: 32px;
    height: 36px;
    padding: 0;
  }

  html:not([lang="nb"]) .main-header .header-actions .lang-summary {
    width: auto;
    min-width: 0;
    height: 36px;
    padding: 0 4px;
    gap: 0;
  }

  html:not([lang="nb"]) .main-header .header-actions .lang-summary .jtp-flag {
    width: 16px;
    height: 11px;
  }

  html:not([lang="nb"]) .main-header .header-actions .lang-summary .lang-caret {
    display: none;
  }

  html:not([lang="nb"]) .main-header .header-actions > .btn {
    flex: 0 0 auto;
    padding: 0.5rem 0.625rem;
    white-space: nowrap;
  }
}

@media (max-width: 389px) {
  html:not([lang="nb"]) .main-header .header-actions .icon-btn:not(.lang-summary) {
    width: 28px;
  }

  html:not([lang="nb"]) .main-header .header-actions > .btn {
    padding: 0.5rem;
  }
}

/* The header's own menus open inside the phone (every locale). The language menu
   (190px wide) and the search panel (320px) were anchored to their button's RIGHT
   edge and opened leftwards past the screen edge once the button sat near the left
   (Norwegian header today; the compact English header above). The language menu
   now opens rightwards from its button; the search panel spans the header, under
   it (its positioned ancestor becomes the sticky .main-header). */
@media (max-width: 600px) {
  .main-header .header-actions .lang-wrapper > .lang-dropdown {
    left: 0;
    right: auto;
  }

  .main-header .header-actions .search-wrapper {
    position: static;
  }

  .main-header .header-actions .search-wrapper > .search-dropdown {
    left: 0.75rem;
    right: 0.75rem;
    width: auto;
  }

  .main-header .header-actions .search-wrapper > .search-dropdown::before {
    display: none;
  }
}

/* Certification info pages (UI-1.1 D2, found by the probe's Android pass once the
   header fitted): beside the 80px icon the hero's text column was a flex item with the
   default min-width:auto, so one long title token ("(CPA/CMA/ACCA)", "HAZMAT/Tanker")
   kept it wider than a phone and widened the layout viewport by 18-61px, pushing the
   dock and the cookie banner off-screen again. On phones the icon now sits above the
   text, which gets the full width, and the 2rem title scales down a little (27-31px on
   360-412px phones), so whole words fit on their lines. Breaking inside a token is
   only the last resort for one wider than the phone. */
@media (max-width: 600px) {
  .cert-info-hero .cert-header {
    flex-wrap: wrap;
  }

  .cert-info-hero .cert-header > :not(.cert-icon-large) {
    flex: 1 1 100%;
    min-width: 0;
  }

  .cert-info-hero .cert-header .cert-title {
    font-size: clamp(1.5rem, 7.5vw, 2rem);
    overflow-wrap: break-word;
  }
}
