/* 页头版式结构样式 —— 复刻 Odoo _header.scss 的核心布局规则。
 *
 * 仅覆盖 template_header_* 实际用到的 class,目的是让**默认之外**的页头版式
 * (汉堡/通栏/竖排/带搜索/销售 1~4/侧栏/圆角盒子)不散架。Odoo 那边这些样式
 * 分散在 website 的多个 SCSS 里,这里按各模板的实际 class 结构提炼成结构规则,
 * 不追求像素级还原(配色/间距仍交给 theme.css 与 bootstrap)。
 */

/* ── 主导航容器 ─────────────────────────────────────────────
   navbar 的直接子元素,横向排列:品牌 | 菜单 | 额外元素。
   不给 flex 的话三者会纵向堆叠(默认版式也依赖它)。

   ★★ **只在 #o_main_nav 自己就是那一行内容容器时才横排** —— 判据是它带着
   `container` 一族的类（各版式写的是 `t-attf-class="o_main_nav #{header_content_width}"`）。

   无条件给 flex 的后果：sales_one / sales_two / sales_three / sales_four 这四套版式的
   `#o_main_nav` 里装的是**上下两行**（顶栏一行 + 主导航一行），横排之后两行**并肩站**，
   每行的 `.container` 从 1320px 缩到 ~800px。表现正是用户报的那两句：「header 宽度
   缩小了和 footer/内容宽度不一致」「大部分版式排版错乱」。真栈判据是
   vertex/scripts/probe_header_width.mjs 里那一行 `行=[0+806 | 806+794]`
   （两行的 x 不同 = 并肩），修好之后是 `行=[0+1600 | 0+1600]`。

   这不是 Bootstrap 的行为：Bootstrap 只给 `.navbar > .container` 一族设 flex
   （bootstrap.min.css 里那条），正是"容器本身才横排"。本仓这条无条件的规则把它扩大到了
   所有 `#o_main_nav`。留着自己这一份而不是纯靠 Bootstrap，是因为「内容宽度 · 窄」那一档
   给的是 `o_container_small`，不在 Bootstrap 的选择器列表里。 */
.o_main_nav.container,
.o_main_nav.container-fluid,
.o_main_nav.o_container_small {
  display: flex;
  align-items: center;
  width: 100%;
  gap: 0;
}

/* 通栏版式:各元素撑满页头高度(o_header_stretch_elts 靠它贴边) */
.o_main_nav.align-items-stretch {
  align-items: stretch;
}

/* ── 三列栅格页头 ───────────────────────────────────────────
   左 | 中(品牌)| 右三栏。子元素用 me-auto / mx-auto / ms-auto 在各自
   栅格列内对齐。汉堡、竖排、带搜索、销售 1~4 的主体都是它。
   模板多半已带 bootstrap `d-grid`(display:grid !important),这里补的是
   列定义;没带 d-grid 的也一并给上 display:grid。 */
.o_grid_header_3_cols {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  width: 100%;
}
/* ── 汉堡/侧栏的移动菜单(真 offcanvas)──────────────────────
   随包的 bootstrap 构建里有一条无作用域的 `.offcanvas{position:static;
   visibility:visible!important;width/height:auto!important}` —— 它把本该收起的
   offcanvas 菜单常驻显示,导致"搜索框+菜单+联系方式"整块散落在页头下面。
   Odoo 给这类菜单挂了 `.o_navbar_mobile`;这里按它把 offcanvas 语义强制找回:
   未 .show 时收起到屏幕外,点汉堡(bootstrap offcanvas JS)才滑出。 */
.o_navbar_mobile.offcanvas {
  position: fixed !important;
  top: 0;
  bottom: 0;
  z-index: 1045;
  width: min(80vw, 400px) !important;
  height: 100% !important;
  background-color: var(--bs-body-bg, #fff) !important;
  visibility: hidden !important;
}
.o_navbar_mobile.offcanvas.offcanvas-start { left: 0; transform: translateX(-100%); }
.o_navbar_mobile.offcanvas.offcanvas-end { right: 0; transform: translateX(100%); }
.o_navbar_mobile.offcanvas.show {
  visibility: visible !important;
  transform: none;
}

/* ── 滚动隐藏条 ─────────────────────────────────────────────
   顶部附加信息条(语言/社交/联系方式)。滚动收起是运行时行为,
   无 JS 时正常显示即可。 */
.o_header_hide_on_scroll {
  width: 100%;
}

/* ── 竖排 / 带搜索:主容器换行,让顶条与主行上下堆叠 ── */
.o_main_nav.flex-wrap {
  flex-wrap: wrap;
}

/* ── 侧栏版式 ───────────────────────────────────────────────
   页头变成左侧固定竖栏:品牌在上、菜单纵向铺开、额外元素在下;正文右移让位。
   仅 ≥lg 生效(窄屏回落普通顶部页头,与 Odoo 一致)。 */
@media (min-width: 992px) {
  /* o_header_sidebar 就挂在 <header id="top"> 本身(不是祖先)——用同元素选择器 */
  header.o_header_sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 260px;
    overflow-y: auto;
    z-index: 1030;
  }
  /* 正文与页脚是页头的兄弟,右移给固定侧栏让出宽度 */
  header.o_header_sidebar ~ main,
  header.o_header_sidebar ~ #bottom {
    margin-left: 260px;
  }
  header.o_header_sidebar .o_main_nav {
    flex-direction: column;
    align-items: stretch;
    height: 100%;
    flex-wrap: nowrap;
  }
  /* 侧栏里的菜单纵向排列(而非横向) */
  header.o_header_sidebar .navbar-nav {
    flex-direction: column;
  }
  /* 侧栏里的 offcanvas 菜单直接内联展开(它就是侧栏内容,不再收起) */
  header.o_header_sidebar .offcanvas {
    position: static !important;
    visibility: visible !important;
    transform: none !important;
    width: auto !important;
    height: auto !important;
    background: transparent !important;
  }
}

/* ── 销售版式的顶/底条与分隔 ──────────────────────────────
   相邻两项之间的一条竖线。**必须脱离文档流**——此前这里写的是
   `display:inline-block; width:1px; align-self:stretch`，两条都不成立：

     ① `align-self` 只对**弹性/网格项**有效，而 ::before 是 <li> 内部的第一个孩子，
        <li> 是普通 block，于是它的高度回落到 auto = 0px ——
        **这条分隔线从来没有画出来过**（实测 ::before 恒为 1px × 0px）。
     ② 高度是 0 也照样要占一个**行盒**（inline-block，line-height 24px）。同一行里
        第一项没有 ::before、后面每一项都凭空多出 24px，父容器 align-items:center
        居中之后，后面那几项的内容就比第一项低 **12px**。
        实测：sales_three 的语言选择器 vs 登录入口（84.2 vs 96.2）、sales_four 的
        菜单 vs 社交/登录/语言（32 vs 44）。两处都是"字明明在一行上却对不齐"，
        而 HTML 与 class 全都是对的。

   模板给这些项传的 `_item_class="position-relative"` 本来就是给绝对定位备下的
   定位面（Odoo 那边就是这么用的）。这里把它补齐——已经带着的项上是空操作。
   偏移取相邻两项间距的一半，间距来自模板的 `gap-*` 工具类，所以按类分档；
   没匹配上的回落 .25rem（线贴着本项左侧，仍在两项之间）。 */
.o_header_separator > * + * {
  position: relative;
}
.o_header_separator > * + *::before {
  content: "";
  position: absolute;
  top: 50%;
  right: calc(100% + var(--o-sep-offset, .25rem));
  transform: translateY(-50%);
  width: 1px;
  height: 1.25em;
  background: currentColor;
  opacity: .25;
  pointer-events: none;
}
.o_header_separator.gap-2 { --o-sep-offset: .25rem; }
.o_header_separator.gap-3 { --o-sep-offset: .5rem; }
.o_header_separator.gap-4 { --o-sep-offset: .75rem; }

/* 销售 2 顶条占位撑开,让三列栅格居中对齐 */
.o_header_sales_two_lang_selector_placeholder,
.o_header_sales_two_txt_elts_placeholder,
.o_header_sales_four_search_placeholder {
  min-width: 0;
}

/* ── 圆角盒子:整条导航加边框圆角 ── */
.o_full_border {
  border: 1px solid var(--o-cc1-border, rgba(0, 0, 0, .1));
  border-radius: 999rem;
}
.o_header_force_no_radius {
  border-radius: 0 !important;
}
.o_border_right_only {
  border-right: 1px solid var(--o-cc1-border, rgba(0, 0, 0, .1));
}

/* ── 导航链接背景(o_navlink_background:链接/按钮悬停底色) ── */
.o_navlink_background:hover,
.o_navlink_background_hover:hover {
  background: rgba(0, 0, 0, .06);
}
.o_navlink_no_background .nav-link {
  background: transparent !important;
}

/* ── 巨型菜单(mega menu)面板 ────────────────────────────────
   复刻 Odoo website.scss 的 `.o_mega_menu`。此前这一块**一条规则都没有**,
   于是面板退化成一个普通的 Bootstrap 下拉:`.dropdown-menu` 只有 min-width、
   不设 width,绝对定位按"收缩包裹"算宽 —— 1440 视口下实测只有 423px。里面那个
   `.container` 被压到 421px,四列类目每列只剩 105px:"Accessories" 这类稍长的
   名字直接溢出到面板外,子类目还会折行。数据是对的,坏的只是版式。

   width:100% 量的是**定位祖先**:菜单项 li 上挂着 position-static
   (见 website_templates.xml 的 submenu 模板),所以祖先是 nav.navbar,面板
   因此与页头同宽 —— 这正是"巨型"菜单的由来。left/top 不必自己写:
   data-bs-display="static" 时 bootstrap 仍会打上 data-bs-popper="static",
   `.dropdown-menu[data-bs-popper]` 已经给了 top:100%/left:0。
   同一条规则还给了 margin-top(2px 的缝),它特异度更高(0,2,0),所以这里
   只能靠 !important 盖 —— Odoo 原文同样是 !important。 */
.o_mega_menu {
  width: 100%;
  padding: 0;                /* 留白归片段自己(pt24 pb24),面板不再夹白边 */
  margin-top: 0 !important;
  border-radius: 0;
  background-clip: unset;    /* padding-box 会在边框内侧留 1px 缝 */
  background-color: transparent; /* 底色交给片段的 o_cc*,面板本身可透明 */
  border: var(--bs-border-width, 1px) solid var(--bs-border-color, #dee2e6);
}

/* ★ 面板透明的前提是"片段自己上底色",而本仓的 theme.css 里有一条 Odoo 没有的
   `.o_colored_level { background-color: transparent }`,它排在 `.o_cc*` 之后、
   特异度相同,于是**把 o_cc 的底色整条抹平了**。十份 s_mega_menu_* 模板的根节点
   全是 `o_colored_level o_cc o_ccN`,所以面板一透明就直接透出页面内容 —— 深色
   首屏上就是深字压深底,一个字也读不出来(比修之前那个挤成一条的白面板更糟)。
   这里只把面板根节点的底色补回来,作用域限死在 .o_mega_menu 内。
   ★ theme.css 那条规则本身是全局隐患(o_cc 的底色对所有带 o_colored_level 的
   片段都不生效),但那是另一件事、影响面是整站,不在这次改动范围内。 */
.o_mega_menu > .o_colored_level {
  background-color: var(--o-cc-bg);
}

/* 面板里的 container 要保住左右留白。Odoo 那边"容器套容器"时内层 padding 会被
   剥掉,所以要重新压回来;本仓暂无那条剥离规则,这里是防回归的护栏。 */
.o_mega_menu .container,
.o_mega_menu .container-fluid {
  padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
  padding-right: calc(var(--bs-gutter-x, 1.5rem) * .5);
}

/* ── 竖排导航(汉堡/侧栏)里的巨型菜单 ──────────────────────
   #top_menu 在 is_vertical_nav 时带 o_mega_menu_is_offcanvas。这时候面板的
   定位祖先在抽屉里,绝对定位那份仍会挤成一条 —— 改成随流排布,和手风琴子菜单
   一样往下顶开;列在窄抽屉里也不该再分栏(Odoo 对 sidebar/hamburger 版式同样
   把列压成 100%)。
   ★ 刻意**不**复刻 Odoo 19 那份 position:fixed 的全屏抽屉版:它靠
   `.o_mega_nav` 的返回箭头关闭,而本仓既没有 odoo_ui_icons 字体、也没有那颗
   按钮的 JS;全屏铺满之后 data-bs-auto-close="outside" 再无"外面"可点,
   等于把访客关在里面。 */
.o_mega_menu_is_offcanvas .o_mega_menu {
  position: static;
  width: 100%;
  max-width: 100%;
  border: none;
  box-shadow: none;
}
.o_mega_menu_is_offcanvas .o_mega_menu [class*="col-"] {
  width: 100%;
  flex: 0 0 auto;
}

/* ── 页头部件壳：排版上要**透明** ─────────────────────────────
   可编辑页头里，活部件外面多了一层壳（`<li class="o_header_part">`），多数部件里面还
   有一层包装（`<ul class="o_header_part_inner">`，见 view/header_parts.xml）。基准模板
   里那个位置只有一个盒子，所以这两层要尽量不改变排版。

   ★ **壳必须是 flex 容器。** 不是为了对齐，是为了 **blockify**：基准模板里品牌
   `<a class="navbar-brand">` 是 `container d-flex` 的**弹性项**，会被规范强制成
   `display:block`，于是它的高度 = 里面那张 40px 的 logo + `.navbar-brand` 的 10px 内边距
   = 50px。套进一个普通 block 壳之后它退回 `display:inline`，高度变成行盒的 33px，
   40px 的图片**溢出**出去 —— 表现是页头整块矮 8px、logo 压在边界上。
   2026-09-01 实测：11 套版式里 7 套的品牌都是 50 → 33。判据只有 getComputedStyle
   的 display，看 HTML 一个字都看不出来。

   菜单的壳**就是**版式里那个 `<ul class="nav navbar-nav …">`（HeaderPart.ShellTag +
   ShellClassExpr），它自己带 display 与方向，排除在外 —— 覆盖它会让侧栏版式的竖排
   菜单变横排。

   ★ 这里**不设 align-items / align-self**。早先设过 `align-self: stretch`（为了接上
   `h-100` 链条），那是**强加**给壳一个基准模板没有的对齐：基准里 `<li>` 在
   `ul.align-items-center` 下是居中、内容高，强制拉伸之后每块部件都变成整行高。
   对齐由父容器说了算，与基准保持一致的唯一办法就是什么都不写。

   只在可编辑页头里生效：公开页上没有壳的版式一个字节都不受影响。 */
/* 父元素是弹性/网格容器时,壳也是 —— 这样壳里的内容照样被 blockify,与基准一致。
   这一位由转换那一步按父元素的 class 打上（core/frontend/header_convert.go 的
   markShellFlex），**不是无条件的**：sales_four 的品牌落在一个普通 <li> 里，
   基准模板下它就是 inline 的 33px，强行 blockify 会让那一行凭空高 17px。 */
.o_header_freeform .o_header_part_flex:not(.navbar-nav) {
  display: flex;
}
/* 内层包装接住版式里的 `h-100` 链条与宽度（基准模板里没有这一层，链条是直接传下去的）。
   `flex:1` 是竖排版式要的：侧栏页头里 `<ul class="navbar-nav gap-2 w-100">` 的每个
   <li> 都被拉到整栏宽，基准模板下里面那颗 `<a class="w-100">` 于是有 259px；
   多一层不撑开的包装之后它只剩 67px —— 侧栏里所有按钮都缩成一小截。 */
.o_header_freeform .o_header_part > .o_header_part_inner {
  height: 100%;
  flex: 1 1 auto;
  min-width: 0;
}
.o_header_freeform .o_header_part_inner > * {
  flex: 1 1 auto;
  min-width: 0;
  /* `h-100` 链条要一路传到内容上。基准模板里 `<a class="… h-100">` 的父级就是被父容器
     拉伸过的那个 <li>，副本里中间多了两层；少这一条链条断在最后一层 —— 通栏版式的
     分隔竖线与按钮从与页头等高（56px）掉到内容高（40px）。
     父级高度是 auto 时 `height:100%` 本来就退回 auto，所以对没有拉伸的版式是空操作。 */
  height: 100%;
}


/* 存量副本的兜底：2026-09-01 之前派生的 `#header_body` 上还带着 `text-break`
   （Bootstrap 的 `word-wrap: break-word !important`）。它是从 #header / #footer 抄来的
   —— 那两块装用户正文，长单词该断行；页头装的是导航条，被挤窄时它让 "Home" 变成
   一行一个字母。新副本已经不带了（internal/controller/header_editable.go），但用户
   自己排过的副本不会被重新生成，只能从样式这一侧压回去。
   两个类的选择器压得过单类的 `.text-break`，`#header`/`#footer` 不受影响。 */
.o_header_freeform.text-break {
  word-wrap: normal !important;
  overflow-wrap: normal !important;
}
