/* NIX — /blog , our markup over website_blog's
   ══════════════════════════════════════════════════════════════════════════
   website_blog renders through website.layout, so views/portal/layout.xml
   already gives it this site's head, foot and stylesheets. What is left is
   Odoo's own furniture: containers sized for a different page, a cover block
   that assumes a photo nobody uploaded, and type at Bootstrap's scale.

   Two layouts, both on markup this repo owns (views/pages/blog.xml): a grid of
   cards for the index and a masthead over one column for the post.

   EVERYTHING IS SCOPED THROUGH #wrapwrap, and that is not decoration. Odoo's
   frontend bundle is linked after these sheets and styles by id, so a class
   cannot outrank it — every rule that has to win against Bootstrap says
   itself at id weight. The rules that do not need to are left plain.

   NO BLIND COLOUR SWEEP. There was one, and it changed more than it fixed:
   this is Odoo's markup and Odoo's bundle, and skinning it from selector
   names is how a page ends up half reskinned. What is here is structure.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── The blog ───────────────────────────────────────────────────────────────
   Two layouts, both on markup this repo owns (views/pages/blog.xml): a grid of
   cards for the index and a masthead-over-column for the post. Everything here
   is scoped through #wrapwrap so it cannot reach the standalone pages, and the
   values are the site's own tokens — no colour is invented for the blog. */
/* The two blocks the tag bar replaces. Hidden, not removed — other views xpath
   into #o_wblog_blog_top, and taking a node another module reaches into out of
   the tree is what broke the registry once already. */
#wrapwrap #o_wblog_blog_top,
#wrapwrap .website_blog nav.navbar { display: none; }

/* BOOTSTRAP'S CONTAINER IS NOT THE MEASURE HERE. `.container` caps itself at
   1320px in steps written against the WINDOW, and the box these posts live in
   is the panel — so on a wide screen the grid stopped short of the panel's own
   edges and the cards were narrower than everything above them. The panel's
   padding is the measure; the container just spans it. */
#wrapwrap.nav-shell .website_blog .container {
  max-width: none;
  width: 100%;
  /* THE SAME INSET THE FOOT TAKES. Zero put the cards 16px outside the column
     everything else in the panel stands on — the four foot columns, the rule
     above them, the tag bar — so the grid was wider than the page it belongs
     to and the left edge of the first card sat proud of every heading under
     it. --space-2 is what shell.css gives the bands; this is the same value
     for the same reason, not a coincidence. */
  padding-inline: var(--space-2);
}

.nix-posts {
  display: grid;
  /* auto-fill with a real floor rather than bootstrap's four breakpoints: the
     card stops being a card below about 260 and the panel's width is not the
     window's, so a breakpoint written against the window would be wrong by the
     rail on every one of them. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-3);
  margin: 0;
}

#wrapwrap .nix-post {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--nix-surface);
  color: var(--nix-text);
  text-decoration: none;
  box-shadow: var(--lift-2);
  transition: transform 260ms var(--ease-out-expo), box-shadow 260ms var(--ease-out-expo);
}

#wrapwrap .nix-post:hover {
  transform: translateY(-4px);
  text-decoration: none;
  box-shadow: var(--lift-3);
}

/* A fixed ratio, not a fixed height: the covers are uploaded by whoever writes
   the post and a height would letterbox half of them. */
.nix-post__cover {
  display: block;
  aspect-ratio: 16 / 10;
  background: color-mix(in oklch, var(--nix-text) 7%, transparent)
              center / cover no-repeat;
}

.nix-post__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
  /* The card's own filler. Cards in a row end on the same line because this
     grows, not because anything is measured. */
  flex: 1;
}

.nix-post__date { color: var(--nix-text-soft); font-size: 13px; }

.nix-post__title {
  font-size: 20px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--nix-text);
}

/* Pushed to the foot by the title's growth above it, so the category sits on
   the card's bottom edge in every card whatever the title does. */
.nix-post__tag {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--nix-text-soft);
  font-size: 13px;
}

.nix-post__tag svg { width: 15px; height: 15px; flex: none; }

.nix-post__draft {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--nix-ink);
  color: var(--nix-on-ink);
  font-size: 12px;
}

#wrapwrap .nix-post { position: relative; }

/* ── The post ─────────────────────────────────────────────────────────────── */
/* The section spans the panel and holds two things: the way back, pinned to
   its top-left corner, and the masthead column centred in it. */
/* THE PANEL IS THE MEASURE, NOT THE WINDOW. The title below is a clamp on
   a viewport unit, and with the rail out the panel is --rail-w narrower than
   the window — so the type was sized for a box it is not in, which is the
   same mistake shell.css collects seven selectors to undo. container-type
   makes cqi mean "this section's width" and the title follows the panel. */
.nix-top {
  position: relative;
  container-type: inline-size;
}

.nix-mast {
  max-width: 720px;
  margin: 0 auto;
  padding: clamp(24px, 5svh, 64px) 0 0;
  text-align: center;
}

/* OUT OF THE FLOW. In it, a post read with the rail shut kept a blank line
   where the button would have been — and the button belongs to the panel's
   corner, not to the 720px column the title is centred in. Colourless at rest:
   a control that is always filled competes with the title under it. */
#wrapwrap .nix-back {
  position: absolute;
  left: 0;
  top: clamp(12px, 2svh, 24px);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44, the touch minimum. It was 40 here and 44 in a second rule for the
     same selector two hundred lines down, which is how the two came to
     disagree — one selector, one block. */
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: var(--radius-pill);
  color: var(--nix-text-soft);
  text-decoration: none;
  transition: background 180ms var(--ease-out-expo), color 180ms var(--ease-out-expo);
}

#wrapwrap .nix-back:hover {
  text-decoration: none;
  color: var(--nix-text);
  background: color-mix(in oklch, var(--nix-text) 8%, transparent);
}

.nix-back svg { width: 16px; height: 16px; }

/* With the rail shut the ring in the corner is the way back, so this would be
   a second one beside it. */
body:not(.is-nav) #wrapwrap .nix-back { display: none; }

/* THE RING, WEARING A CHEVRON. While the rail is shut on a post page the ring
   is the way back, and a control has to look like what it does: the circle
   opens out and a chevron is drawn in its place, from two borders of a square
   turned on its corner — the same shape the back button carries, at the size
   the ring already occupies. 24, with the ring: it was 22 from before the
   trigger grew, so the one control that is both a menu and a way back
   changed size depending on which it was. */
.site-menu__trigger.is-back {
  border-color: transparent;
  width: 24px;
  height: 24px;
}

/* background: none is what makes it a chevron. The base rule paints this
   pseudo-element in --nix-text — it is one stroke of the cross — and the
   override changed its size, its borders and its angle but not its fill, so
   what rendered was a solid ink square on its corner with two invisible
   borders drawn on the ink. A diamond, under a comment describing a chevron. */
.site-menu__trigger.is-back::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 58%;
  width: 8px;
  height: 8px;
  background: none;
  border-left: 1.6px solid var(--nix-text);
  border-bottom: 1.6px solid var(--nix-text);
  transform: translate(-50%, -50%) rotate(45deg);
}

/* AND IT IS A CROSS AGAIN WHEN THE MENU IS OPEN. `.is-back::before` ties on
   specificity with `[aria-expanded="true"]::before` and this sheet loads
   last, so a reader on a post with the rail shut who opened the menu got the
   chevron plus one lone stroke of the X. */
.site-menu__trigger.is-back[aria-expanded="true"] {
  border-color: transparent;
}

.site-menu__trigger.is-back[aria-expanded="true"]::before {
  width: 24px;
  height: 1.5px;
  background: var(--nix-text);
  border: 0;
  transform: translate(-50%, -50%) rotate(45deg);
}

.nix-mast__kicker {
  margin: 0 0 20px;
  color: var(--nix-text-soft);
  font-size: 13px;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* .nix-mast .nix-mast__title, not .nix-mast__title: the element is an <h1>
   and `.website_blog h1` further down is (0,1,1), so the bare class lost and
   the masthead rendered at the generic size — including Bootstrap's own
   margin-bottom, which reopened 8px under a title that measures its own. */
.nix-mast .nix-mast__title {
  margin: 0;
  font-size: clamp(30px, 6cqi, 52px);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--nix-text);
}

.nix-mast__sub {
  margin: 16px 0 0;
  font-size: 18px;
  color: var(--nix-text-soft);
}

/* Date, reading time and author on one line. Wrapping rather than shrinking:
   on a narrow panel three facts and two separators do not fit, and a line that
   breaks between them still reads as one line of facts. */
.nix-mast__meta {
  margin: 20px 0 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  color: var(--nix-text-soft);
  font-size: 14px;
}

.nix-mast__fact { display: inline-flex; align-items: center; gap: 7px; }

.nix-mast__fact svg { width: 15px; height: 15px; flex: none; opacity: .75; }

/* The gap between facts, spent as space rather than as a separator: three
   icons already say where one fact ends and the next begins. */
.nix-mast__meta { column-gap: 22px; }

/* Two chevrons at the foot of a post, and nothing else. */
.nix-pager {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: clamp(40px, 7svh, 80px) 0 clamp(24px, 4svh, 48px);
}

#wrapwrap .nix-pager__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  /* A square with the site's small radius, not a pill. The round ones read as
     two floating buttons; these read as two keys. */
  border-radius: var(--radius-sm);
  background: var(--nix-surface);
  color: var(--nix-text);
  text-decoration: none;
  box-shadow: var(--lift-2);
  transition: transform 200ms var(--ease-out-expo);
}

#wrapwrap .nix-pager__arrow:hover { transform: translateY(-2px); text-decoration: none; }

.nix-pager__arrow svg { width: 18px; height: 18px; }

/* Wider than the words above it, because it is a picture and they are a
   sentence — the measure that makes a title readable makes an image small. */
.nix-mast__cover {
  width: min(1080px, 100%);
  margin: clamp(24px, 5svh, 56px) auto 0;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-xl);
  background: color-mix(in oklch, var(--nix-text) 7%, transparent)
              center / cover no-repeat;
}

/* One column, centred, and nothing beside it. This was a two-column grid with
   a facts sidebar; the facts moved onto the masthead and the column is the
   whole of it now. 68ch is the one number here that is not a token: it is a
   count of characters, which is what a line length is. */
.nix-post-main {
  container-type: inline-size;
  width: min(1080px, 100%);
  margin: clamp(32px, 6svh, 72px) auto 0;
}

.nix-read { max-width: 68ch; margin: 0 auto; }

/* ── Odoo's own furniture ─────────────────────────────────────────────────
   The cover block reserves a photo's worth of height whether or not a post
   has one; a post with no image should not open with a screenful of nothing.
   The type scale is Bootstrap's and this site's is not.

   The container rules that used to stand here are gone: they capped
   `.website_blog .container` at min(1180px, 92vw) and were overridden on
   every blog page by the id-weight rule at the top of this file, because the
   layout always puts .nav-shell on #wrapwrap. */
.website_blog { color: var(--nix-text); }

.website_blog .o_record_cover_container {
  min-height: 0 !important;
  background: none !important;
}

.website_blog .o_record_cover_image { border-radius: var(--radius-xl); }

/* cqi, not vw, for the reason the masthead's own title takes it: the panel is
   --rail-w narrower than the window whenever the rail is out, so vw measures a
   box this type is not in. .nix-post-main carries the container. */
.website_blog .o_wblog_post_title,
.website_blog h1 {
  font-size: clamp(28px, 5.5cqi, 48px);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--nix-text);
}

.website_blog .o_wblog_post_subtitle,
.website_blog .lead {
  color: var(--nix-text-soft);
  font-weight: 400;
}

.website_blog h2 { font-size: clamp(20px, 3.2cqi, 28px); font-weight: 400; }

.website_blog h3 { font-size: 18px; font-weight: 400; }

.website_blog p { color: var(--nix-text); line-height: 1.65; }

.website_blog a { color: var(--nix-text); }

/* Post cards in the list: the site's surface and radius rather than
   Bootstrap's bordered card. */
.website_blog .o_wblog_post_page_item,
.website_blog .card {
  background: var(--nix-surface);
  border: 0;
  border-radius: var(--radius-xl);
  overflow: hidden;
}

/* Odoo's own buttons carry Bootstrap's blue. The site is monochrome. */
.website_blog .btn-primary,
.website_blog .btn-outline-primary {
  background: var(--nix-ink);
  border-color: var(--nix-ink);
  color: var(--nix-on-ink);
  border-radius: var(--radius-pill);
}

.website_blog .btn-primary:hover,
.website_blog .btn-outline-primary:hover { opacity: .85; }

/* NO DARK BLOCK HERE ANY MORE. Every lifted surface on this page — the post
   card, its hover, the pager's keys — spends --lift-*, and those tokens are
   already `none` on a dark ground: a shadow is light being blocked, and on
   #101010 what the browser draws instead is a black smear. The three rules
   that used to name them by hand were the same sentence said twice, and the
   second saying is what drifts. See tokens.css. */

/* Focus on the three controls a reader uses to move between posts. The back
   button's size is up with the rest of it: it was declared here as well for
   one round, which is how the 40 and the 44 came to disagree in the first
   place — and both copies then carried a comment saying the other did not
   exist. One selector, one block. */
#wrapwrap .nix-post:focus-visible,
#wrapwrap .nix-pager__arrow:focus-visible,
#wrapwrap .nix-back:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}
