/* Hectorrrs — Hector's personal site, on ECH0. Ported from the Design Studio
   prototype (prototypes/hectorrrs/layer.css).
   Only DS tokens: no colour literal, no border (law 1 — a surface step or the
   canvas between blocks separates them, never a line). */

/* ── Hero ────────────────────────────────────────────────────────────── */
.hx-hero { text-align: center; }

/* The chevrons: the only way through the scenes (layer.js). Up at the top of
   the screen, down at its foot; shown once the quote is in, bobbing gently
   toward where they go; each sinks into the depth at its end of the deck. */
.hx-cue {
  position: fixed;
  z-index: 10;
  left: 50%;
  translate: -50% 0;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  color: var(--text-muted);
  /* ECH0's depth: it waits back in it (dim, blurred, a little smaller),
     comes forward sharp, and sinks back (blur 5px, scale .94) on scroll. */
  opacity: 0; filter: blur(6px); scale: .94;
  transition: opacity 700ms cubic-bezier(.22,1,.36,1), filter 700ms cubic-bezier(.22,1,.36,1),
              scale 700ms cubic-bezier(.22,1,.36,1), color var(--dur-fast) var(--ease-out);
}
.hx-cue.is-on { opacity: 1; filter: none; scale: 1; }
.hx-cue.is-on.is-gone { opacity: 0; filter: blur(5px); scale: .94; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .hx-cue, .hx-cue.is-on.is-gone { filter: none; scale: 1; } }
.hx-cue:hover { color: var(--text); }
.hx-cue svg { animation: hx-bob 2.4s ease-in-out infinite; }
.hx-cue--down { bottom: max(28px, env(safe-area-inset-bottom)); }
.hx-cue--up { top: max(28px, env(safe-area-inset-top)); }
.hx-cue--up svg { animation-name: hx-bob-up; }
@keyframes hx-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(6px); } }
@keyframes hx-bob-up { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .hx-cue svg { animation: none; } }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
.hx-title {
  margin: 0 0 var(--space-5);
  font-size: clamp(var(--text-2xl), 8vw, 72px);
  font-weight: var(--weight-display);
  line-height: 1.02;
  letter-spacing: -0.02em;
}
.hx-lede {
  /* The same voice as the story below it: size, weight, leading, measure. */
  max-width: 30em;
  margin: 0 auto;
  font-size: var(--text-xl);
  font-weight: var(--weight-display);
  line-height: 1.4;
  color: var(--text-muted);
}
.hx-cta {
  display: inline-block;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-pill);
  text-decoration: none;
}

/* ── Sections ────────────────────────────────────────────────────────── */
.hx-section { text-align: center; }

/* Every section a full screen, its content in the middle — ECH0's way
   (nix_website blank.css). min-height, not height: a section with more than
   a screen of content grows instead of clipping. */
.hx-hero, .hx-section {
  min-height: 100vh; min-height: 100dvh;
  box-sizing: border-box;
  padding: 48px 0;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
}
.hx-hero > *, .hx-section > * { max-width: 100%; }
.hx-cards, .hx-posts { width: 100%; }
.hx-h2 {
  margin: 0 0 var(--space-6);
  font-size: var(--text-xl);
  font-weight: var(--weight-display);
}
.hx-prose { max-width: 36em; margin: 0 auto; }
.hx-prose p, .hx-contact p {
  margin: 0 0 var(--space-4);
  font-size: var(--text-md);
  line-height: 1.6;
  color: var(--text-muted);
}

.hx-more {
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.hx-more:hover { color: var(--text); }

/* The story: one paragraph, lit word by word with the scroll (layer.js) —
   ECH0's story on nix.cm: an unlit word stands back in the depth (dim,
   blurred, a little smaller) and comes forward sharp as it lights. */
.hx-story-text {
  max-width: 30em;
  margin: 0 auto var(--space-7);
  font-size: var(--text-xl);
  font-weight: var(--weight-display);
  line-height: 1.4;
}
.story-word { display: inline-block; transform-origin: 50% 60%; will-change: opacity, filter, transform; }
.hx-social { display: flex; justify-content: center; gap: var(--space-3); }
.hx-social-link {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.hx-social-link:hover { background: var(--surface-panel); color: var(--text); }

/* Projects: the chosen one up top (its mark | a rule | what it is), the
   cards along the bottom choose it. The section spreads the two apart over
   its full screen. The rule is an ornament drawn as a block, not a border
   (law 1 is about borders). */
.hx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.hx-section.hx-projects { justify-content: space-between; padding: 14vh 0 9vh; }
.hx-feature {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  column-gap: var(--space-5);
  width: 100%;
  text-align: left;
}
.hx-feature-thumb {
  justify-self: end;
  width: 210px; aspect-ratio: 2 / 1;
  border-radius: var(--radius-lg);
  background: var(--action-bg);
  color: var(--action-text);
  display: grid; place-items: center;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.hx-feature-mark { font-size: var(--text-lg); }
.hx-feature-rule { width: 1px; height: 176px; background: var(--text); margin-top: -4px; }
.hx-feature-info { justify-self: start; }
.hx-panel { display: flex; flex-direction: column; gap: 2px; text-transform: uppercase; font-size: var(--text-sm); color: var(--text); }
.hx-panel-name {
  margin-bottom: 2px;
  font-size: var(--text-lg);
  color: var(--text);
  text-decoration: none;
}
.hx-panel-name:hover { color: var(--text-muted); }
/* A panel coming in: ECH0's depth (dim, blurred, a little smaller → sharp). */
.hx-panel.is-in { animation: hx-depth 420ms cubic-bezier(.22,1,.36,1) both; }
@keyframes hx-depth { from { opacity: 0; filter: blur(6px); transform: scale(.94); } to { opacity: 1; filter: none; transform: none; } }

.hx-section.hx-projects .hx-cards {
  /* A slider: one row that scrolls sideways and settles a card at a time;
     the card in the middle is the chosen one (layer.js). The padding lets
     the first and last cards reach the middle; the edges fade out. */
  position: relative;
  display: flex;
  gap: var(--space-6);
  /* Edge to edge: --hx-vw is the page's width without the scrollbar
     (layer.js); 100vw would count the scrollbar and scroll the page. */
  width: var(--hx-vw, 100vw);
  max-width: none;
  padding: var(--space-2) calc(var(--hx-vw, 100vw) / 2 - 155px);
  box-sizing: border-box;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 18%, #000 82%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 18%, #000 82%, transparent);
  cursor: grab;
}
.hx-section.hx-projects .hx-cards::-webkit-scrollbar { display: none; }
.hx-section.hx-projects .hx-cards.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.hx-section.hx-projects .hx-card { flex: 0 0 310px; scroll-snap-align: center; }
.hx-card {
  aspect-ratio: 310 / 178;
  border-radius: var(--radius-xl);
  background: var(--surface-panel);
  color: var(--text-muted);
  display: flex; align-items: flex-end;
  padding: var(--space-5);
  text-align: left;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.hx-card:hover { background: var(--surface-fill); color: var(--text); }
.hx-card.is-on { background: var(--action-bg); color: var(--action-text); }
.hx-card-name { font-size: var(--text-md); }
/* What is not out yet: a question mark in the middle of the card. */
.hx-card--soon { align-items: center; justify-content: center; }
.hx-card-q { font-size: var(--text-2xl); font-weight: var(--weight-display); line-height: 1; }

/* Writing: a list of rows, each a quiet surface on hover. */
.hx-posts { list-style: none; max-width: 36em; margin: 0 auto var(--space-5); padding: 0; text-align: left; }
.hx-post {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4);
  margin: 0 calc(-1 * var(--space-4));
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.hx-post:hover { background: var(--surface-panel); }
.hx-post-date { color: var(--text-muted); font-size: var(--text-sm); white-space: nowrap; }

/* ── Footer ──────────────────────────────────────────────────────────── */
.hx-foot {
  padding: var(--space-7) 0;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* ── The hero as a quote ──────────────────────────────────────────────────
   The sentence and the name under it in small capitals. The words come in
   (layer.js), the name last — out of the same depth (dim, blurred, a little
   smaller). */
.hx-quote { margin: 0; display: flex; flex-direction: column; align-items: center; }
.hx-quote-text { margin: 0; }
.hx-quote-by {
  margin-top: var(--space-6);
  font-size: var(--text-sm);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.hx-quote-by {
  opacity: .16; filter: blur(6px); transform: scale(.94);
  transition: opacity 700ms cubic-bezier(.22,1,.36,1), filter 700ms cubic-bezier(.22,1,.36,1),
              transform 700ms cubic-bezier(.22,1,.36,1);
}
.hx-quote.is-lit .hx-quote-by { opacity: 1; filter: none; transform: none; }
.hx-quote.is-lit .hx-quote-by { transition-delay: var(--by-delay, 1500ms); }
@media (prefers-reduced-motion: reduce) {
  .hx-quote-by { opacity: 1; filter: none; transform: none; transition: none; }
}

/* ── The hero's words, out of the depth (ECH0's story on nix.cm) ─────────
   Each word starts dim, blurred and a little smaller and comes forward
   sharp, 70ms after the one before (layer.js splits the sentence). */
.hx-word {
  display: inline-block;
  opacity: .16; filter: blur(6px); transform: scale(.94);
  transition: opacity 700ms cubic-bezier(.22,1,.36,1), filter 700ms cubic-bezier(.22,1,.36,1),
              transform 700ms cubic-bezier(.22,1,.36,1);
  transition-delay: calc(var(--w, 0) * 70ms + 150ms);
}
.hx-lede.is-lit .hx-word { opacity: 1; filter: none; transform: none; }
@media (prefers-reduced-motion: reduce) { .story-word { opacity: 1 !important; filter: none !important; transform: none !important; }
  .hx-word { opacity: 1; filter: none; transform: none; transition: none; } }

/* ── ECH0's entrance cascade (nix_website blank.css, verbatim) ────────────
   Each block's pieces drop in from 14px above, one after another, 70ms
   apart, the first time the block comes on screen (layer.js). Waiting
   pieces are hidden; the class comes off when the drop ends, so nothing
   keeps a transform it did not have. */
html .ti-wait { opacity: 0; }
.ti-drop { animation: ti-drop 520ms cubic-bezier(.22,1,.36,1) both; animation-delay: calc(var(--i, 0) * 70ms + 120ms); }
@keyframes ti-drop { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { html .ti-wait { opacity: 1; } .ti-drop { animation: none; } }

/* ── The deck: every section a fixed scene (layer.js) ─────────────────────
   The scenes sit on top of each other, fixed, each a full screen in the
   column's width; layer.js sets their depth (opacity, blur, scale) as the
   chevron moves from one to the next. The page itself does not scroll. */
html.hx-deck, html.hx-deck body { overflow: hidden; height: 100%; }
/* No deck (reduced motion): no chevrons, the page scrolls. */
html:not(.hx-deck) .hx-cue { display: none; }
html.hx-deck .hx main > section {
  position: fixed;
  top: 0; left: 0; right: 0;
  margin: 0 auto;
  width: min(960px, 100% - 32px);
  height: 100vh; height: 100dvh;
  min-height: 0;
  will-change: opacity, filter, scale;
}
html.hx-deck .hx-foot { position: absolute; left: 0; right: 0; bottom: 0; }

/* ── Preloader ───────────────────────────────────────────────────────
   One of the orb's butterflies flies in from anywhere to the centre and
   breaks into an ASCII shock wave; the page shows through as it spreads.
   Drawn on one canvas by layer.js; once per session. */
.hx-pre {
  position: fixed;
  inset: 0;
  z-index: 1000;
  transition: opacity var(--dur-slow) var(--ease-out), visibility 0s linear var(--dur-slow);
}
/* The ring is spreading: the page shows through behind it. */
/* The same ground as the page, on its own layer: a gradient cannot fade as a
   background-color, so the layer fades instead when the page shows through. */
.hx-pre::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, var(--surface-ground-top) 0%, var(--surface-canvas) 55%, var(--surface-ground-low) 100%);
  transition: opacity 700ms var(--ease-out);
}
.hx-pre-cv { position: relative; z-index: 1; }
.hx-pre.is-open::before { opacity: 0; }
.hx-pre.is-open { pointer-events: none; }
.hx-pre.is-done { opacity: 0; visibility: hidden; }
.hx-pre-cv { display: block; width: 100%; height: 100%; }

/* ── Phone ───────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  /* The chevrons to the very edges (past the notch and the home bar), a size
     smaller, and every scene keeps clear of them top and bottom. */
  .hx-cue { width: 36px; height: 36px; }
  .hx-cue svg { width: 22px; height: 22px; }
  .hx-cue--down { bottom: calc(env(safe-area-inset-bottom) + 10px); }
  .hx-cue--up { top: calc(env(safe-area-inset-top) + 10px); }
  html.hx-deck .hx main > section {
    padding-top: calc(env(safe-area-inset-top) + 60px);
    padding-bottom: calc(env(safe-area-inset-bottom) + 60px);
  }
  .hx-hero, .hx-section { padding: 32px 0; }
  .hx-section.hx-projects { padding: 10vh 0 6vh; }
  .hx-feature-thumb { width: 120px; }
  .hx-feature-rule { height: 120px; }
  /* Smaller on a phone, so the neighbours show on both sides; the padding
     is half of what is left, so the first and last can still reach the middle. */
  .hx-section.hx-projects .hx-cards { padding: var(--space-2) 24vw; gap: var(--space-3); }
  .hx-section.hx-projects .hx-card { flex-basis: 52vw; padding: var(--space-4); }
  .hx-card-q { font-size: var(--text-xl); }
  .hx-article { padding: var(--space-5); }
}

/* ── Odoo's own pages on this site: the blog, a post, the 404 ─────────────
   views/layout.xml puts these sheets after Odoo's frontend bundle and marks
   #wrapwrap .hx-odoo. Odoo's header and footer are gone; the ground, the
   type and the colours are ECH0's; Bootstrap's white surfaces step aside. */
.hx-odoo { background: transparent; color: var(--text); font-family: var(--font); }
.hx-odoo :is(h1, h2, h3, h4, h5, h6, p, li, span, div) { font-family: var(--font); }
.hx-odoo :is(h1, h2, h3) { font-weight: var(--weight-display); color: var(--text); }
.hx-odoo a { color: var(--text); text-decoration-color: color-mix(in srgb, var(--text) 30%, transparent); }
.hx-odoo a:hover { color: var(--text-muted); }
.hx-odoo :is(.text-muted, .text-secondary, small) { color: var(--text-muted) !important; }
.hx-odoo :is(.bg-white, .bg-light, .bg-body, .o_wblog_post_page_cover, section.s_cover, .o_record_cover_container) {
  background: transparent !important;
}
.hx-odoo :is(.card, .o_wblog_post) { background: var(--surface-panel); border: 0; border-radius: var(--radius-lg); }
.hx-odoo :is(.btn-primary, .btn-secondary) {
  background: var(--action-bg); color: var(--action-text); border: 0; border-radius: var(--radius-pill);
}
.hx-odoo main { min-height: calc(100vh - 80px); }
.hx-home {
  display: block;
  width: max-content;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
  font-size: var(--text-sm);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-muted) !important;
  text-decoration: none;
}
.hx-home:hover { color: var(--text) !important; }
