/* Growise Tech site styles */

@font-face { font-family: "Poppins"; font-style: normal; font-weight: 500; font-display: swap; src: url(../fonts/poppins-latin-500-normal.woff2) format("woff2"); }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 600; font-display: swap; src: url(../fonts/poppins-latin-600-normal.woff2) format("woff2"); }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 700; font-display: swap; src: url(../fonts/poppins-latin-700-normal.woff2) format("woff2"); }
@font-face { font-family: "Poppins"; font-style: italic; font-weight: 300; font-display: swap; src: url(../fonts/poppins-latin-300-italic.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url(../fonts/ibm-plex-sans-latin-400-normal.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: italic; font-weight: 400; font-display: swap; src: url(../fonts/ibm-plex-sans-latin-400-italic.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url(../fonts/ibm-plex-sans-latin-500-normal.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url(../fonts/ibm-plex-sans-latin-600-normal.woff2) format("woff2"); }

:root {
  --ink: #0F2A4A;
  --ink-deep: #0B2140;
  --blue: #2196F3;
  --action: #1565C0;
  --action-hover: #0F4F9C;
  --graphite: #565757;
  --teal: #0B6E63;
  --teal-bright: #12A08F;
  --amber: #A85708;
  --amber-bright: #E08A1E;
  --mist: #EEF4FB;
  --line: #D9E3EF;
  --white: #FFFFFF;
  --on-dark: #C9D6E6;

  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  --font-head: "Poppins", "Segoe UI", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;

  --wrap: 1200px;
  --gutter: clamp(20px, 4vw, 40px);
  --space-section: clamp(64px, 8vw, 112px);
  --radius: 6px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--graphite);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-head);
  color: var(--ink);
  margin: 0;
  font-weight: 600;
}
h1 { font-size: clamp(2.25rem, 1.35rem + 3.3vw, 3.7rem); line-height: 1.08; letter-spacing: -0.025em; font-weight: 700; }
h2 { font-size: clamp(1.75rem, 1.2rem + 1.9vw, 2.5rem); line-height: 1.15; letter-spacing: -0.018em; }
h3 { font-size: 1.1875rem; line-height: 1.3; letter-spacing: -0.005em; }

p { margin: 0; }
ul, ol, dl, dd, figure, blockquote { margin: 0; padding: 0; }
img { max-width: 100%; height: auto; display: block; }

a { color: var(--action); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--action-hover); }
:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; border-radius: 2px; }

.container { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 100;
  background: var(--ink); color: var(--white); padding: 10px 16px; border-radius: var(--radius);
}
.skip-link:focus { top: 12px; color: var(--white); }

/* Placeholder marker for facts awaiting confirmation */
.tbc { background: #FFF4C2; color: #5B4A00; padding: 0 4px; border-radius: 3px; font-weight: 500; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 12px 22px;
  font-family: var(--font-head); font-weight: 600; font-size: 0.975rem; line-height: 1.2;
  border-radius: var(--radius); border: 2px solid transparent;
  text-decoration: none; transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.btn-primary { background: var(--action); color: var(--white); }
.btn-primary:hover { background: var(--action-hover); color: var(--white); }
.btn-quiet { color: var(--ink); border-color: var(--line); background: var(--white); }
.btn-quiet:hover { border-color: var(--ink); color: var(--ink); }
.btn-light { background: var(--white); color: var(--ink); }
.btn-light:hover { background: var(--mist); color: var(--ink); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; }

/* Small segment glyph, taken from the logo ring */
.arc::before {
  content: ""; display: inline-block; flex: none; width: 15px; height: 15px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%232196F3' d='M2.2 0.6A14.5 14.5 0 0 1 15.4 13.8L8.8 14.4A8 8 0 0 0 1.6 7.2Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Header */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--white); border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; min-height: 76px; }
.brand { display: inline-flex; flex: none; }
.brand img { height: 36px; width: auto; }

.site-nav { display: flex; align-items: center; gap: 36px; }
.nav-list { list-style: none; display: flex; align-items: center; gap: 32px; }
/* Nothing in the header row may fold onto a second line. A two-word label
   stacked beside one-word labels gives the row three different heights, and
   it happened silently in a 25px band of laptop widths. If the row ever stops
   fitting, nowrap makes it overflow instead, which the QA sweep catches. */
.nav-list > li > a, .menu-trigger, .nav-cta { white-space: nowrap; }
.nav-list > li > a, .menu-trigger {
  font-family: var(--font-head); font-weight: 500; font-size: 0.97rem; color: var(--ink);
  text-decoration: none; background: none; border: 0; padding: 8px 0; cursor: pointer;
}
.nav-list > li > a:hover, .menu-trigger:hover { color: var(--action); }
.menu-trigger { display: inline-flex; align-items: center; gap: 8px; }
.menu-trigger::after {
  content: ""; width: 7px; height: 7px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform .15s ease;
}
.menu-trigger[aria-expanded="true"]::after { transform: translateY(1px) rotate(225deg); }

.has-menu { position: relative; }
.mega {
  position: absolute; top: calc(100% + 18px); left: -32px; width: 720px;
  display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 8px 32px;
  padding: 28px 32px 24px; background: var(--white);
  border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 24px 48px rgba(15, 42, 74, 0.12);
  visibility: hidden; opacity: 0; transform: translateY(-6px);
  transition: opacity .15s ease, transform .15s ease, visibility 0s linear .15s;
}
.has-menu:hover .mega, .has-menu:focus-within .mega, .menu-trigger[aria-expanded="true"] + .mega {
  visibility: visible; opacity: 1; transform: none; transition-delay: 0s;
}
.mega::before { content: ""; position: absolute; left: 0; right: 0; top: -20px; height: 20px; }
.mega-title { font-family: var(--font-head); font-weight: 600; color: var(--ink); font-size: 0.95rem; margin-bottom: 6px; }
.mega-note { font-size: 0.85rem; line-height: 1.4; margin-bottom: 10px; }
.mega ul { list-style: none; }
.mega li a { display: block; padding: 6px 0; font-size: 0.95rem; color: var(--ink); text-decoration: none; }
.mega li a:hover { color: var(--action); text-decoration: underline; }
.mega-all { grid-column: 1 / -1; margin-top: 12px; padding-top: 14px; border-top: 1px solid var(--line); font-weight: 500; font-size: 0.95rem; }

.nav-toggle {
  display: none; align-items: center; gap: 10px;
  font-family: var(--font-head); font-weight: 500; font-size: 0.95rem; color: var(--ink);
  background: none; border: 1px solid var(--line); border-radius: var(--radius); padding: 9px 14px; cursor: pointer;
}
.nav-toggle-bars { width: 18px; height: 12px; position: relative; border-top: 2px solid currentColor; border-bottom: 2px solid currentColor; }
.nav-toggle-bars::after { content: ""; position: absolute; left: 0; right: 0; top: 3px; border-top: 2px solid currentColor; }
/* on the narrowest phones the word and the logo together overrun the gutter */
@media (max-width: 340px) {
  .nav-toggle { gap: 0; padding: 9px 11px; font-size: 0; }
  .brand img { height: 32px; }
}

/* The full nav needs 1086px to sit on one line. The menu takes over with
   margin to spare, because the alternative was a band where neither fit. */
@media (max-width: 1120px) {
  .nav-toggle { display: inline-flex; }
  .site-nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--white); border-bottom: 1px solid var(--line);
    padding: 8px var(--gutter) 24px; max-height: calc(100vh - 76px); overflow-y: auto;
  }
  .site-header.nav-open .site-nav { display: flex; }
  .nav-list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav-list > li { border-bottom: 1px solid var(--line); }
  .nav-list > li > a, .menu-trigger { display: flex; width: 100%; justify-content: space-between; padding: 16px 0; font-size: 1.05rem; }
  .mega {
    position: static; width: auto; display: none; grid-template-columns: 1fr; gap: 20px;
    padding: 4px 0 20px; border: 0; box-shadow: none; border-radius: 0;
    visibility: visible; opacity: 1; transform: none; transition: none;
  }
  .has-menu:hover .mega, .has-menu:focus-within .mega { display: none; }
  .menu-trigger[aria-expanded="true"] + .mega { display: grid; }
  .mega::before { display: none; }
  .nav-cta { margin-top: 20px; }
}

/* Official Odoo Partner badge */
.partner-badge {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 8px 16px 8px 12px; margin-bottom: 26px;
  border: 1px solid #D9C4D2; border-radius: 999px; background: #EFE5EC;
  text-decoration: none; font-size: 0.9rem; line-height: 1.2;
  transition: border-color .15s ease, background-color .15s ease;
}
.partner-badge:hover { border-color: #714B67; background: #E6D6E0; }
.partner-badge-logo { height: 18px; width: auto; flex: none; }
.partner-badge-text { font-family: var(--font-head); font-weight: 600; color: #5E3E56; }
.partner-badge-verify { color: #714B67; border-left: 1px solid #D0B8C6; padding-left: 12px; }
@media (max-width: 420px) { .partner-badge-verify { display: none; } }

/* Hero */
.hero { padding-block: clamp(48px, 7vw, 96px) clamp(40px, 5vw, 72px); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: clamp(32px, 5vw, 72px); align-items: center; }
.hero h1 { max-width: 16ch; }
.hero-lead { margin-top: 24px; font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.2rem); line-height: 1.6; max-width: 58ch; }
.hero .actions { margin-top: 36px; }
.credentials { list-style: none; display: flex; flex-wrap: wrap; gap: 10px 22px; margin-top: 36px; }
.credentials li { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; font-size: 0.925rem; color: var(--ink); }
.credentials a { color: var(--ink); }
.credentials a:hover { color: var(--action); }

.hero-ring { margin: 0; }
.hero-ring svg { width: 100%; height: auto; max-width: 620px; margin-inline: auto; display: block; overflow: visible; }
.ring-seg { fill: var(--blue); }
.ring-open { fill: var(--white); stroke: var(--amber-bright); stroke-width: 3.5; stroke-linejoin: round; }
.ring-label { font-family: var(--font-body); font-weight: 500; font-size: 22px; fill: var(--ink); }
.ring-label-open { font-family: var(--font-head); font-weight: 600; font-size: 22px; fill: var(--amber); }
.ring-sub { font-family: var(--font-body); font-size: 17px; fill: var(--graphite); }
.ring-center { font-family: var(--font-head); font-weight: 600; font-size: 30px; fill: var(--ink); letter-spacing: -0.01em; }
.ring-center-sub { font-family: var(--font-body); font-size: 16px; fill: var(--graphite); }

@media (prefers-reduced-motion: no-preference) {
  .ring-seg, .ring-open { transform-box: view-box; transform-origin: 360px 280px; animation: seg-in .55s cubic-bezier(.2,.7,.2,1) both; }
  .ring-open { stroke-dasharray: 560; stroke-dashoffset: 560; animation: seg-draw .9s ease-out 1.05s forwards; }
  .ring-text { animation: fade-in .6s ease 1.2s both; }
}
@keyframes seg-in { from { opacity: 0; transform: scale(.9) rotate(-8deg); } to { opacity: 1; transform: none; } }
@keyframes seg-draw { to { stroke-dashoffset: 0; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-ring svg { max-width: 560px; }
}
@media (max-width: 480px) { .ring-sub { display: none; } .ring-label { font-size: 26px; } .ring-label-open { font-size: 27px; } }

/* Client logos */
.clients { padding-block: 8px clamp(56px, 7vw, 88px); }
.clients > .container { padding-top: 36px; border-top: 1px solid var(--line); }
.logo-marquee {
  margin-top: 8px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.logo-track { display: flex; width: max-content; animation: logo-marquee 48s linear infinite; }
.logo-row { list-style: none; display: flex; align-items: center; gap: 72px; padding-right: 72px; margin: 0; }
.logo-row li {
  position: relative; display: flex; align-items: center; justify-content: center;
  height: 176px; padding-bottom: 68px; flex: none;
}
.logo-row img { transition: transform .22s ease; transform-origin: center center; }
.logo-item:hover, .logo-item:focus-visible { z-index: 2; }
.logo-row { position: relative; }
.logo-item:hover img, .logo-item:focus-visible img { transform: scale(1.4); }
.logo-detail {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%) translateY(6px);
  opacity: 0; pointer-events: none; text-align: center; white-space: nowrap;
  transition: opacity .2s ease, transform .2s ease;
}
.logo-item:hover .logo-detail, .logo-item:focus-visible .logo-detail { opacity: 1; transform: translateX(-50%); }
.logo-name { display: block; font-family: var(--font-head); font-weight: 600; font-size: 0.9rem; color: var(--ink); }
.logo-meta { display: block; margin-top: 2px; font-size: 0.8rem; color: var(--graphite); }
@media (prefers-reduced-motion: reduce) { .logo-row img, .logo-detail { transition: none; } }
.logo-row img { width: auto; max-width: none; }
@keyframes logo-marquee { from { transform: translateX(-33.3333%); } to { transform: translateX(0); } }
.logo-marquee:hover .logo-track, .logo-marquee:focus-within .logo-track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .logo-track { animation: none; transform: none; }
  .logo-marquee { overflow-x: auto; }
  .logo-row + .logo-row { display: none; }
}
@media (max-width: 720px) { .logo-row { gap: 48px; padding-right: 48px; } .logo-row li { height: 150px; padding-bottom: 54px; } }

/* Sections */
.section { padding-block: var(--space-section); }
.section--mist { background: var(--mist); }
.section--navy { background: var(--ink); color: var(--on-dark); }
.section--navy h2, .section--navy h3 { color: var(--white); }

.section-head { max-width: 62ch; margin-bottom: clamp(40px, 5vw, 60px); }
.section-head p { margin-top: 16px; font-size: 1.0625rem; }
.section-head--row { max-width: none; display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; flex-wrap: wrap; }
.section-head--row a { font-weight: 500; }

.link-light { color: var(--white); font-weight: 500; }
.link-light:hover { color: var(--on-dark); }

/* Services by stage */
.stages { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 56px 72px; align-items: start; }
.stage--build { grid-row: span 2; }
.stage { padding-top: 22px; border-top: 3px solid var(--blue); }
.stage--advise { border-top-color: var(--teal-bright); }
.stage--run { border-top-color: var(--amber-bright); }
.stage-title { font-size: 1.5rem; }
.stage-sub { margin-top: 6px; margin-bottom: 20px; }
.service-list { list-style: none; border-bottom: 1px solid var(--line); }
.service-list li { border-top: 1px solid var(--line); }
.service-list a { display: block; padding: 18px 0; text-decoration: none; }
.service-name { display: block; font-family: var(--font-head); font-weight: 600; font-size: 1.0625rem; color: var(--ink); }
.service-desc { display: block; margin-top: 4px; font-size: 0.975rem; line-height: 1.55; color: var(--graphite); }
.service-list a:hover .service-name { color: var(--action); text-decoration: underline; text-underline-offset: 3px; }
.stage-note { margin-top: 14px; font-size: 0.9rem; }
@media (max-width: 900px) { .stages { grid-template-columns: 1fr; } .stage--build { grid-row: auto; } }

/* How Odoo works together */
.flow-steps { list-style: none; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 32px 28px; }
.flow-step { position: relative; padding-top: 40px; }
.flow-step::before {
  content: ""; position: absolute; top: 0; left: 0; width: 16px; height: 16px;
  border: 3px solid var(--blue); border-radius: 50%; background: var(--white); z-index: 1;
}
.flow-step::after { content: ""; position: absolute; top: 7px; left: 22px; right: -22px; height: 2px; background: var(--line); }
.flow-step:last-child::after { display: none; }
.flow-step h3 { font-size: 1.0625rem; }
.flow-apps { margin-top: 6px; font-size: 0.875rem; font-weight: 500; color: var(--action); }
.flow-step p:last-child { margin-top: 10px; font-size: 0.95rem; line-height: 1.55; }
.flow-note { margin-top: clamp(40px, 5vw, 56px); padding-top: 28px; border-top: 1px solid var(--line); max-width: 70ch; }
@media (max-width: 1060px) { .flow-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } .flow-step:nth-child(3)::after { display: none; } }
@media (max-width: 640px) {
  .flow-steps { grid-template-columns: 1fr; gap: 28px; }
  .flow-step { padding-top: 0; padding-left: 40px; }
  .flow-step::before { top: 4px; }
  .flow-step::after, .flow-step:nth-child(3)::after { display: block; top: 26px; bottom: -26px; left: 7px; right: auto; width: 2px; height: auto; }
  .flow-step:last-child::after { display: none; }
}

/* Why Growise */
.why-grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 48px 80px; }
.why-intro p { margin-top: 18px; }
.why-points { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 44px 48px; }
.point { padding-top: 22px; border-top: 2px solid var(--ink); }
.point p { margin-top: 12px; font-size: 1rem; }
@media (max-width: 900px) { .why-grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .why-points { grid-template-columns: 1fr; } }

/* Delivery phases */
.phases { list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 44px 40px; }
.phase svg { width: 56px; height: 56px; display: block; }
.phase h3 { margin-top: 18px; font-size: 1.0625rem; }
.phase p { margin-top: 8px; font-size: 0.95rem; line-height: 1.55; }
.mini-on { fill: var(--blue); }
.phase:nth-child(3) .mini-on, .phase:nth-child(4) .mini-on { fill: #17A3C7; }
.phase:nth-child(5) .mini-on, .phase:nth-child(6) .mini-on { fill: var(--teal-bright); }
.phase:nth-child(7) .mini-on { fill: #2FC08A; }
.mini-off { fill: none; stroke: rgba(255, 255, 255, 0.35); stroke-width: 1.5; }
.mini-num { font-family: var(--font-head); font-weight: 600; font-size: 15px; fill: var(--white); }
.process-foot { margin-top: clamp(40px, 5vw, 56px); }
@media (max-width: 1060px) { .phases { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 820px) { .phases { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .phases { grid-template-columns: 1fr; } }

/* Project portfolio */
.portfolio { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.tile {
  display: flex; flex-direction: column; gap: 28px;
  padding: 32px; border-radius: 14px; min-height: 320px;
  color: rgba(255, 255, 255, 0.82); text-decoration: none;
  transition: filter .15s ease;
}
.tile--wide { grid-column: span 2; }
.tile-logo { margin: 0; }
.tile-logo img { width: auto; }
.tile-body { margin-top: 4px; }
.tile-context { font-size: 0.9rem; color: rgba(255, 255, 255, 0.7); }
.tile-scope {
  margin-top: 10px; color: var(--white);
  font-family: var(--font-head); font-weight: 500;
  font-size: 1.0625rem; line-height: 1.45; letter-spacing: -0.01em; max-width: 44ch;
}
.tile--wide .tile-scope { font-size: 1.25rem; line-height: 1.4; max-width: 40ch; }
.tile--wide .tile-context { font-size: 0.95rem; }
.tile-foot {
  margin-top: auto;
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 8px 24px; padding-top: 18px; border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.tile-apps { font-size: 0.85rem; }
.tile-link { font-family: var(--font-head); font-weight: 600; font-size: 0.9rem; color: var(--white); text-decoration: underline; text-underline-offset: 4px; }
.tile-note { font-size: 0.85rem; color: rgba(255, 255, 255, 0.6); }
a.tile:hover { filter: brightness(1.22); color: rgba(255, 255, 255, 0.82); }
@media (prefers-reduced-motion: reduce) { .tile { transition: none; } }
@media (max-width: 900px) { .portfolio { grid-template-columns: repeat(2, minmax(0, 1fr)); } .tile--wide { grid-column: span 2; } }
@media (max-width: 640px) { .portfolio { grid-template-columns: 1fr; } .tile--wide { grid-column: span 1; } .tile { min-height: 0; padding: 28px 24px; } }

/* Industries band */
.section--slim { padding-block: clamp(40px, 5vw, 64px); }
.industries-band { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px 48px; }
.industries-band h2 { font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem); }
.industries-band p { margin-top: 12px; max-width: 70ch; }

/* Industry slider */
.sectors { padding-bottom: clamp(48px, 6vw, 72px); }
.sectors-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 20px 48px; margin-bottom: clamp(28px, 4vw, 40px); }
.sectors-head p { margin-top: 12px; max-width: 62ch; }
.sectors-nav { display: flex; align-items: center; gap: 12px; }
.sectors-hint { font-size: 0.9rem; color: var(--graphite); margin-right: 4px; }

.sectors-marquee {
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -ms-overflow-style: none;
  touch-action: pan-x; cursor: grab; overscroll-behavior-x: contain;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}
.sectors-marquee::-webkit-scrollbar { display: none; }
.sectors-marquee:active { cursor: grabbing; }
.sectors-belt { --card: 300px; --card-gap: 4px; display: flex; width: max-content; }
.sectors-set {
  flex: none; display: flex; gap: var(--card-gap); padding-right: var(--card-gap);
  width: calc(var(--count, 9) * (var(--card) + var(--card-gap)));
}
.sector {
  position: relative; flex: none; width: var(--card); height: 440px;
  display: flex; align-items: flex-end; overflow: hidden; text-decoration: none;
}
.sector-shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.sector::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(8, 20, 36, .15) 0%, rgba(8, 20, 36, .55) 45%, rgba(8, 20, 36, .88) 100%);
}
.sector-body { position: relative; z-index: 2; padding: 28px 26px 30px; }
.sector-name { display: block; font-family: var(--font-head); font-weight: 600; font-size: 1.35rem; color: var(--white); letter-spacing: -0.01em; }
.sector-line { display: block; margin-top: 10px; font-size: 0.95rem; line-height: 1.5; color: rgba(255, 255, 255, .82); }
.sector:hover .sector-name { text-decoration: underline; text-underline-offset: 4px; }

@media (max-width: 620px) { .sectors-belt { --card: 260px; } .sector { height: 380px; } }

/* Client reviews */
.voices-grid { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 2fr); gap: 32px 56px; align-items: center; }
.voices-intro p { margin-top: 16px; max-width: 34ch; }
.voice-nav { display: flex; gap: 12px; margin-top: 28px; }
.voice-btn {
  width: 48px; height: 48px; border-radius: 50%; border: 1px solid var(--line);
  background: var(--white); color: var(--ink); font-size: 1.1rem; line-height: 1;
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.voice-btn:hover { border-color: var(--ink); }
.voice-btn--go { background: var(--action); border-color: var(--action); color: var(--white); }
.voice-btn--go:hover { background: var(--action-hover); border-color: var(--action-hover); }
.voice-btn[disabled] { opacity: .35; cursor: default; }

.voices-track {
  display: flex; gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; padding-bottom: 4px; scrollbar-width: none;
}
.voices-track::-webkit-scrollbar { display: none; }
.voice {
  flex: 0 0 calc(50% - 12px); scroll-snap-align: start;
  display: flex; flex-direction: column; gap: 22px;
  background: var(--mist); border-radius: 14px; padding: 32px 32px 28px;
}
.voice-mark { font-family: var(--font-head); font-weight: 700; font-size: 2.4rem; line-height: .6; color: var(--blue); }
.voice blockquote p { font-size: 1.0625rem; line-height: 1.6; color: var(--ink); }
.voice figcaption { margin-top: auto; display: flex; align-items: center; gap: 16px; }
.voice-photo { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; flex: none; }
.voice-initials {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--white);
  font-family: var(--font-head); font-weight: 600; font-size: 1rem; letter-spacing: .02em;
}
.voice-who { display: flex; flex-direction: column; }
.voice-name { font-family: var(--font-head); font-weight: 600; color: var(--ink); }
.voice-role { font-size: 0.95rem; }
@media (prefers-reduced-motion: reduce) { .voices-track { scroll-behavior: auto; } }
@media (max-width: 1060px) { .voices-grid { grid-template-columns: 1fr; } .voice-nav { margin-top: 20px; } }
@media (max-width: 820px) { .voice { flex-basis: calc(100% - 8px); padding: 28px 24px; } }

/* Closing call to action */
.cta-final { position: relative; overflow: hidden; background: linear-gradient(135deg, #0F2A4A 0%, #123E6B 55%, #0E5B63 100%); color: var(--on-dark); padding-block: clamp(72px, 9vw, 120px); }
.cta-final h2 { color: var(--white); max-width: 18ch; }
.cta-final p { margin-top: 18px; max-width: 56ch; font-size: 1.0625rem; }
.cta-final .actions { margin-top: 32px; }
.cta-ring { position: absolute; right: -140px; top: 50%; width: 560px; transform: translateY(-50%); pointer-events: none; }
.cta-ring path { fill: none; stroke: rgba(255, 255, 255, 0.09); stroke-width: 2; }
.cta-final .container { position: relative; }
@media (max-width: 900px) { .cta-ring { opacity: .6; right: -260px; } }

/* ---- about ----
   Two columns of prose rather than cards. The content here is argument, not a
   set of parallel features, and a card implies the four things in it are the
   same kind of thing. They are not: two of them are what the firm does and
   two are what it refuses. */
.about-cols {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px); align-items: start;
}
.about-cols h3 { font-size: 1.0625rem; }
.about-cols h3 + p { margin-top: 10px; }
.about-cols p + h3 { margin-top: clamp(26px, 3vw, 34px); }
.about-cols p { font-size: 1rem; line-height: 1.65; }

/* The facts strip, in its light-section form. The one in a masthead is white
   type on navy and cannot be reused here. */
.about-facts {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px 28px; margin: 0 0 clamp(36px, 4.5vw, 52px);
  padding-bottom: clamp(28px, 3.5vw, 36px); border-bottom: 1px solid var(--line);
}
.about-facts dt { font-size: 0.78rem; color: var(--graphite); }
.about-facts dd {
  margin-top: 4px; font-family: var(--font-head); font-weight: 600;
  font-size: 0.95rem; line-height: 1.4; color: var(--ink);
}

/* The six phases, numbered by the list itself rather than by markup, so the
   numbering stays right if one is added or removed. */
.about-phases {
  list-style: none; counter-reset: ph;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(26px, 3vw, 40px);
}
.about-phases li { counter-increment: ph; }
.about-phases li::before {
  content: counter(ph); display: block; font-family: var(--font-mono);
  font-size: 0.78rem; font-weight: 500; color: var(--action); margin-bottom: 10px;
}
.about-phases h3 { font-size: 1.0625rem; }
.about-phases p { margin-top: 8px; font-size: 0.975rem; line-height: 1.6; color: var(--graphite); }

/* A gap in the page, marked where it falls rather than collected at the
   bottom, so whoever fills it can see what the sentence around it needs. */
.todo-inline {
  margin-top: clamp(26px, 3vw, 34px); padding: 14px 18px; max-width: 76ch;
  font-size: 0.93rem; line-height: 1.6; color: #43351C;
  background: #FDF6E7; border: 1px dashed #D7A94B; border-radius: 10px;
}
.todo-inline span {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase; color: #8A5B06;
  margin-right: 10px;
}
.todo-inline + .todo-inline { margin-top: 10px; }

@media (max-width: 900px) {
  .about-cols { grid-template-columns: minmax(0, 1fr); }
  .about-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .about-phases { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .about-facts, .about-phases { grid-template-columns: minmax(0, 1fr); }
}

/* ---- the exhibition band ----
   Three photographs of the same size in one row, large enough that the stand,
   the sign on it and the faces all read. They are the content of this
   section, not decoration in it, so they get the full width of the container
   rather than a column beside some text. */
.stand-shots {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 24px); margin-top: clamp(26px, 3.5vw, 40px);
}
.stand-shot {
  margin: 0; border-radius: 14px; overflow: hidden; background: #E4EAF1;
  border: 1px solid var(--line);
}
.stand-shot img { width: 100%; height: auto; display: block; aspect-ratio: 4 / 3; object-fit: cover; }
.stand-note {
  margin-top: 18px; font-size: 0.9rem; color: var(--graphite);
}
@media (max-width: 760px) {
  /* Three across a phone makes each one too small to tell apart, which is the
     one thing this section cannot afford. One at a time instead. */
  .stand-shots { grid-template-columns: minmax(0, 1fr); }
}

/* Footer */
.site-footer { background: var(--ink-deep); color: var(--on-dark); font-size: 0.95rem; }
.footer-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 40px 48px; padding-block: 64px 48px; }
.footer-brand img { height: 34px; width: auto; }
.footer-brand p { margin-top: 18px; max-width: 34ch; }
.footer-brand a { display: inline-block; margin-top: 14px; }
.footer-title { font-family: var(--font-head); font-size: 0.95rem; font-weight: 600; color: var(--white); margin-bottom: 14px; }
.site-footer ul { list-style: none; }
.site-footer li + li { margin-top: 8px; }
.site-footer a { color: var(--white); text-decoration: none; }
.site-footer a:hover { text-decoration: underline; color: var(--white); }
.site-footer address { font-style: normal; }
.footer-note { font-size: 0.8rem; color: #8EA3BC; margin-left: 6px; }
.footer-contact p { margin-top: 10px; }
.footer-base { display: flex; flex-wrap: wrap; gap: 12px 28px; align-items: center; padding-block: 24px 32px; border-top: 1px solid rgba(255, 255, 255, 0.12); font-size: 0.875rem; }
.footer-base ul { display: flex; gap: 20px; }
.footer-base li + li { margin-top: 0; }
.footer-tm { flex-basis: 100%; color: #8FA3BC; }
@media (max-width: 900px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .footer-brand { grid-column: 1 / -1; } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: 1fr; } }

/* WhatsApp button */
.wa-float {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 18px 10px 12px; border-radius: 999px;
  background: #25D366; color: var(--white); text-decoration: none;
  font-family: var(--font-head); font-weight: 600; font-size: 0.95rem; line-height: 1;
  box-shadow: 0 10px 24px rgba(11, 33, 64, 0.22);
  transition: background-color .15s ease;
}
.wa-float:hover { background: #1DB855; color: var(--white); }
.wa-icon { width: 30px; height: 30px; flex: none; }
@media (max-width: 640px) {
  .wa-float { padding: 11px; right: 16px; bottom: 16px; }
  .wa-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* Resources and posts */
.post-list { display: grid; gap: 0; border-bottom: 1px solid var(--line); max-width: 860px; }
.post-card { padding-block: 32px; border-top: 1px solid var(--line); }
.post-card h2 { margin-top: 10px; font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.7rem); }
.post-card h2 a { color: var(--ink); text-decoration: none; }
.post-card h2 a:hover { color: var(--action); text-decoration: underline; text-underline-offset: 4px; }
.post-card p:last-child { margin-top: 12px; max-width: 70ch; }

.post-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 0.9rem; color: var(--graphite); }
.post-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--blue); display: inline-block; }
.post-back { margin-bottom: 24px; font-size: 0.95rem; }
.post h1 { max-width: 20ch; }
.post .post-meta { margin-top: 18px; }

.prose { max-width: 68ch; margin-top: clamp(32px, 4vw, 48px); }
.prose h2 { margin-top: 44px; font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.75rem); }
.prose h3 { margin-top: 32px; }
.prose p { margin-top: 18px; font-size: 1.0625rem; line-height: 1.7; }
.prose ul, .prose ol { margin-top: 18px; padding-left: 22px; }
.prose li { margin-top: 8px; line-height: 1.7; }
.prose li::marker { color: var(--blue); }
.prose strong { color: var(--ink); font-weight: 600; }
.prose blockquote { margin-top: 24px; padding-left: 20px; border-left: 3px solid var(--blue); color: var(--ink); }
.prose a { text-decoration: underline; text-underline-offset: 3px; }

.post-cta { max-width: 68ch; margin-top: clamp(48px, 6vw, 72px); padding: 32px; border-radius: 14px; background: var(--mist); }
.post-cta h2 { font-size: 1.4rem; }
.post-cta p { margin-top: 12px; }
.post-cta .btn { margin-top: 22px; }

/* ============================================================
   Service pages: built as documents, not as showcase bands.
   No colour bands, a reading column with a sticky contents rail,
   and section rules instead of alternating backgrounds.
   ============================================================ */
.svc { --accent: var(--action); --accent-soft: #E7F0FA; }
.svc--advise { --accent: var(--teal); --accent-soft: #E2F2EF; }
.svc--run { --accent: var(--amber); --accent-soft: #F8EDE1; }

/* Breadcrumb */
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; font-size: 0.875rem; }
.crumbs li + li::before { content: "/"; margin-right: 8px; color: #A9BACB; }
.crumbs a { color: var(--graphite); text-decoration: none; }
.crumbs a:hover { color: var(--accent); text-decoration: underline; }
.crumbs [aria-current] { color: var(--ink); }

/* Compact masthead: a third the height of the homepage hero */
.masthead { background: var(--accent-soft); border-bottom: 1px solid rgba(15, 42, 74, 0.1); }
.masthead .container { padding-block: 24px 30px; }
.masthead h1 {
  margin-top: 18px; font-size: clamp(1.9rem, 1.4rem + 1.7vw, 2.6rem);
  line-height: 1.12; max-width: 22ch;
}
.masthead-lead { margin-top: 14px; max-width: 64ch; font-size: 1.0625rem; line-height: 1.6; }


/* Document body: contents rail beside a reading column */
.doc { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 0 64px; padding-block: 0 clamp(48px, 6vw, 72px); }
.doc-rail { position: sticky; top: 100px; align-self: start; padding-top: 44px; }
.rail-title { font-size: 0.8rem; color: var(--graphite); }
.doc-rail ol { list-style: none; counter-reset: toc; margin-top: 12px; }
.doc-rail ol li { counter-increment: toc; }
.doc-rail ol a {
  display: flex; gap: 10px; padding: 7px 0; font-size: 0.925rem; line-height: 1.35;
  color: var(--graphite); text-decoration: none; border-left: 2px solid transparent; padding-left: 12px;
  margin-left: -14px;
}
.doc-rail ol a::before { content: counter(toc); color: #A9BACB; font-variant-numeric: tabular-nums; }
.doc-rail ol a:hover { color: var(--ink); }
.doc-rail ol a[aria-current] { color: var(--ink); font-weight: 500; border-left-color: var(--accent); }
.doc-rail ol a[aria-current]::before { color: var(--accent); }

.rail-cta { margin-top: 28px; padding: 20px; border: 1px solid var(--line); border-radius: 6px; }
.rail-cta p { font-size: 0.925rem; line-height: 1.5; }
.rail-cta .btn { width: 100%; margin-top: 14px; font-size: 0.875rem; min-height: 44px; padding-inline: 10px; }
.rail-cta .rail-or { margin-top: 12px; font-size: 0.85rem; }

.doc-body { min-width: 0; padding-top: 8px; }
.doc-sec { padding-block: clamp(36px, 4vw, 52px); border-top: 1px solid var(--line); }
.doc-sec:first-child { border-top: 0; }
.doc-sec > h2 { font-size: clamp(1.4rem, 1.15rem + 1vw, 1.85rem); }
.doc-sec > h2 + p { margin-top: 14px; max-width: 68ch; line-height: 1.7; }

@media (max-width: 1000px) {
  .doc { grid-template-columns: 1fr; gap: 0; }
  .doc-rail { position: static; padding-top: 32px; border-bottom: 1px solid var(--line); padding-bottom: 28px; }
  .doc-rail ol { columns: 2; column-gap: 32px; }
  .rail-cta { display: none; }
}

/* Failure modes: numbered prose, not cards */
.modes { list-style: none; counter-reset: mode; margin-top: 28px; }
.mode { counter-increment: mode; display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 0 20px; padding-block: 22px; border-top: 1px solid var(--line); }
.mode::before {
  content: counter(mode); font-family: var(--font-head); font-weight: 600; font-size: 1.1rem;
  color: var(--accent); line-height: 1.5;
}
.mode h3 { font-size: 1.05rem; max-width: 40ch; }
.mode p { margin-top: 8px; max-width: 66ch; line-height: 1.65; }
@media (max-width: 560px) { .mode { grid-template-columns: 1fr; gap: 6px; } }

/* Scope: a plain two-column reference list */
.scope { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 44px; margin-top: 26px; }
.scope > div { padding-block: 15px; border-top: 1px solid var(--line); }
.scope dt { font-family: var(--font-head); font-weight: 600; font-size: 0.975rem; color: var(--ink); }
.scope dd { margin-top: 4px; font-size: 0.95rem; line-height: 1.55; }
@media (max-width: 620px) { .scope { grid-template-columns: 1fr; } }

/* The seven phases, as a ledger */
.ledger { list-style: none; margin-top: 28px; border-bottom: 1px solid var(--line); }
.phase-row { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 0 20px; padding-block: 26px; border-top: 1px solid var(--line); }
.phase-no { font-family: var(--font-head); font-weight: 600; font-size: 1.5rem; color: var(--accent); line-height: 1; }
.phase-row h3 { font-size: 1.1rem; }
.phase-facts { margin-top: 14px; display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 10px 20px; }
.phase-facts dt { font-size: 0.875rem; color: var(--graphite); }
.phase-facts dd { font-size: 0.975rem; line-height: 1.6; max-width: 62ch; }
.phase-facts .ph-get { color: var(--ink); font-weight: 500; }
@media (max-width: 620px) {
  .phase-row { grid-template-columns: 1fr; gap: 10px; }
  .phase-facts { grid-template-columns: 1fr; gap: 2px 0; }
  .phase-facts dt { margin-top: 10px; }
}

/* Apps */
/* ============ Odoo apps: four feeds, one ledger ============
   Not a module list. The four parts of the business sit across the top, wires
   run down from each into a single ledger, and a pulse travels each wire to
   say which way the data goes. */
.flowgraph { margin-top: clamp(26px, 3vw, 36px); }

.feeds {
  list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 2%; row-gap: 14px;
}
.feed {
  background: var(--white); border: 1px solid #E3E8EE; border-radius: 14px;
  padding: clamp(18px, 1.8vw, 22px);
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.feed:hover {
  border-color: #CBD8E6; box-shadow: 0 12px 28px rgba(15, 42, 74, 0.08); transform: translateY(-2px);
}
.feed h3 { font-family: var(--font-head); font-weight: 600; font-size: 1rem; color: var(--ink); }
.feed > p { margin-top: 7px; font-size: 0.9rem; line-height: 1.55; }

/* the wires */
.wires { display: block; width: 100%; height: 64px; overflow: visible; }
.wire { fill: none; stroke: #BBCBDD; stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.wire-pulse {
  stroke: var(--blue); stroke-width: 2.5; stroke-linecap: round;
  stroke-dasharray: 16 420; stroke-dashoffset: 436;
  animation: wire-run 3.2s linear infinite;
}
@keyframes wire-run { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .wire-pulse { display: none; }
  .feed { transition: none; }
  .feed:hover { transform: none; }
}

/* the ledger everything posts into */
.hub {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 22px 44px; align-items: center;
  padding: clamp(22px, 2.6vw, 32px); border-radius: 16px; color: var(--on-dark);
  background:
    radial-gradient(620px 240px at 88% 0%, rgba(33, 150, 243, 0.2), transparent 62%),
    linear-gradient(150deg, #0C2341 0%, #0F2A4A 58%, #10273F 100%);
  box-shadow: 0 20px 48px rgba(10, 32, 60, 0.22);
}
/* where the wires land */
.hub::before, .hub::after {
  content: ''; position: absolute; left: 50%; width: 9px; height: 9px;
  margin-left: -4.5px; border-radius: 50%; background: var(--blue);
  box-shadow: 0 0 0 4px rgba(33, 150, 243, 0.2);
}
.hub::before { top: -4.5px; }
.hub::after { bottom: -4.5px; }
@media (max-width: 680px) { .hub::before, .hub::after { display: none; } }
.hub-say h3 { font-family: var(--font-head); font-weight: 600; font-size: 1.15rem; color: var(--white); }
.hub-say p { margin-top: 8px; font-size: 0.95rem; line-height: 1.65; color: #B6C9DD; max-width: 54ch; }
.app-row.app-row--hub { margin-top: 0; grid-template-columns: repeat(3, auto); gap: 14px 28px; }
.app-row--hub .app-name { color: #DCE7F2; white-space: nowrap; }
.app-row--hub .app img { filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25)); }

/* Each app is a chip: the icon, then the name, on one line. Two columns inside
   a card, so the icons align down the card and a long name like Manufacturing
   never collides with its neighbour or drops onto a second line. */
.app-row {
  list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 16px; margin-top: clamp(18px, 2vw, 24px); align-items: center;
}
.app { display: flex; align-items: center; gap: 11px; min-width: 0; }
.app img, .app-mark { width: 32px; height: 32px; flex: none; display: block; }
.app img { transition: transform .18s ease; }
.feed:hover .app img { transform: scale(1.1); }
@media (prefers-reduced-motion: reduce) { .app img { transition: none; } .feed:hover .app img { transform: none; } }
.app-mark {
  display: grid; place-items: center; border-radius: 9px;
  background: var(--mist); color: var(--action);
  font-family: var(--font-head); font-weight: 600; font-size: 0.9rem;
  box-shadow: inset 0 0 0 1px rgba(15, 42, 74, 0.12);
}
.app-name { font-size: 0.875rem; line-height: 1.3; color: var(--ink); min-width: 0; }

/* Narrower than four columns the wires line up with nothing, so they give way
   to a single stem that still reads as everything running into one place. */
@media (max-width: 1120px) {
  .app-row { gap: 13px 12px; }
  .app { gap: 9px; }
  .app img, .app-mark { width: 29px; height: 29px; }
  .app-name { font-size: 0.82rem; }
}
@media (max-width: 680px) {
  .feeds { grid-template-columns: 1fr; }
  .hub { grid-template-columns: 1fr; }
  .wires path { display: none; }
  .wires {
    height: 36px;
    background: linear-gradient(180deg, #CBD8E6, var(--blue)) center / 2px 100% no-repeat;
  }
  .flowgraph > .wires:last-of-type { background-image: linear-gradient(180deg, var(--blue), #CBD8E6); }
  .app-row, .app-row.app-row--hub { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .app img, .app-mark { width: 32px; height: 32px; }
  .app-name { font-size: 0.875rem; }
}
@media (max-width: 440px) {
  .app-row, .app-row.app-row--hub { grid-template-columns: 1fr; gap: 12px; }
}

.doc-note {
  margin-top: 26px; max-width: 68ch; font-size: 0.95rem; line-height: 1.65;
  color: var(--graphite); padding-left: 18px; border-left: 2px solid #DDE3EA;
}

/* Proof: picture cards, duotoned into the palette */
.proof { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; margin-top: 28px; }
.proof-card { display: flex; flex-direction: column; text-decoration: none; color: var(--graphite); }
.proof-shot { position: relative; aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden; background: var(--ink); }
.proof-shot img.proof-bg { width: 100%; height: 100%; object-fit: cover; display: block; }
.proof-shot::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(12, 32, 58, 0.1) 0%, rgba(12, 32, 58, 0.78) 100%);
}
.proof-mark { position: absolute; left: 20px; right: 20px; bottom: 18px; z-index: 1; }
.proof-mark img { width: auto; }
.proof-where { margin-top: 14px; font-size: 0.85rem; color: var(--graphite); }
.proof-what { margin-top: 6px; font-size: 0.975rem; line-height: 1.55; color: var(--ink); }
.proof-apps { margin-top: 10px; font-size: 0.85rem; color: var(--graphite); }
.proof-card .proof-link { margin-top: auto; padding-top: 12px; font-weight: 500; font-size: 0.9rem; color: var(--action); }
.proof-card:hover .proof-link { text-decoration: underline; text-underline-offset: 3px; }
.proof-card:hover .proof-shot img.proof-bg { transform: scale(1.04); }
.proof-shot img.proof-bg { transition: transform .4s ease; }
@media (prefers-reduced-motion: reduce) { .proof-shot img.proof-bg { transition: none; } }
@media (max-width: 860px) { .proof { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .proof { grid-template-columns: 1fr; } }

/* ---- a proof section with nothing verified to put in it yet ----
   Deliberately loud, and deliberately not styled like the page around it. It
   is a note to the people building the site, not content, so it has to be
   impossible to mistake for a finished section in a review. Same job as the
   dashed frame that stands in for a missing office photograph. */
.proof--todo {
  display: block; padding: clamp(22px, 3vw, 30px);
  background: repeating-linear-gradient(135deg, #FFF9EC 0 14px, #FEF4DE 14px 28px);
  border: 1px dashed #D7A94B; border-radius: 14px;
}
.todo-flag {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: #8A5B06;
}
.todo-why {
  margin-top: 10px; max-width: 62ch; font-size: 1rem; line-height: 1.6; color: #43351C;
}
.todo-cols {
  display: grid; grid-template-columns: minmax(0, 0.78fr) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 40px); margin-top: 24px;
}
.todo-cols h3 {
  font-size: 0.83rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: #8A5B06;
}
.todo-asks, .todo-leads { margin-top: 12px; padding-left: 20px; }
.todo-asks li, .todo-leads li {
  font-size: 0.93rem; line-height: 1.55; color: #43351C;
}
.todo-asks li + li, .todo-leads li + li { margin-top: 8px; }
.todo-leads { list-style: none; padding-left: 0; }
.todo-leads li { position: relative; padding-left: 20px; }
.todo-leads li::before {
  content: "?"; position: absolute; left: 0; top: 0;
  font-family: var(--font-mono); font-weight: 600; color: #B5811C;
}
@media (max-width: 700px) { .todo-cols { grid-template-columns: 1fr; } }

/* FAQs */
.faqs { margin-top: 20px; border-bottom: 1px solid var(--line); }
.faq { border-top: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; display: flex; gap: 24px; justify-content: space-between;
  align-items: baseline; padding-block: 18px;
  font-family: var(--font-head); font-weight: 600; font-size: 1rem; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 12px; height: 12px; margin-top: 5px;
  background: linear-gradient(var(--accent), var(--accent)) center / 100% 2px no-repeat,
              linear-gradient(var(--accent), var(--accent)) center / 2px 100% no-repeat;
  transition: transform .18s ease;
}
.faq[open] summary::after { transform: rotate(90deg); background-size: 100% 2px, 0 100%; }
.faq summary:hover { color: var(--accent); }
.faq-a { padding-bottom: 20px; }
.faq-a p { max-width: 68ch; line-height: 1.7; font-size: 0.975rem; }
@media (prefers-reduced-motion: reduce) { .faq summary::after { transition: none; } }

/* Next services */
/* the foot of the page: where to go next, grouped as the services hub groups
   them. Names only, because by here the reader wants the link, not the pitch. */
.nextup { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px 40px; margin-top: 24px; }
.nextup-col { padding-top: 16px; border-top: 1px solid var(--line); }
.nextup-col h3 { font-family: var(--font-head); font-weight: 600; font-size: 0.95rem; color: var(--ink); }
.nextup-col > p { margin-top: 5px; font-size: 0.875rem; line-height: 1.5; }
.nextup-col ul { list-style: none; margin-top: 14px; display: grid; gap: 9px; }
.nextup-col li a { font-size: 0.95rem; }
@media (max-width: 760px) { .nextup { grid-template-columns: 1fr; gap: 20px; } }


/* ============ Services index (hub) ============ */
.idx { max-width: 860px; padding-block: clamp(40px, 5vw, 60px) clamp(48px, 6vw, 72px); }
.idx-stage + .idx-stage { margin-top: clamp(40px, 4vw, 56px); }
.idx-head { padding-top: 18px; border-top: 3px solid var(--action); }
.idx-stage--advise .idx-head { border-top-color: var(--teal); }
.idx-stage--run .idx-head { border-top-color: var(--amber); }
.idx-head h2 { font-size: 1.45rem; }
.idx-head p { margin-top: 5px; }
.idx-list { margin-top: 14px; border-bottom: 1px solid var(--line); }
.idx-row { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 4px 32px; padding-block: 16px; border-top: 1px solid var(--line); }
.idx-row dt a { font-family: var(--font-head); font-weight: 600; font-size: 1.0625rem; text-decoration: none; }
.idx-row dt a:hover { text-decoration: underline; text-underline-offset: 3px; }
.idx-row dd { font-size: 0.975rem; line-height: 1.55; }
.idx-stage--advise .idx-row dt a { color: var(--teal); }
.idx-stage--run .idx-row dt a { color: var(--amber); }
@media (max-width: 680px) { .idx-row { grid-template-columns: 1fr; } }

.flow-steps--three { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; }
.flow-steps--three .flow-step:nth-child(3)::after { display: none; }
@media (max-width: 760px) { .flow-steps--three { grid-template-columns: 1fr; } }
.nb { white-space: nowrap; }

/* ============ Service masthead: dark, with the phase machine ============ */
.masthead {
  background:
    radial-gradient(900px 420px at 86% 18%, rgba(33, 150, 243, 0.22), transparent 62%),
    radial-gradient(700px 400px at 8% 96%, rgba(14, 91, 99, 0.3), transparent 60%),
    linear-gradient(140deg, #0C2341 0%, #0F2A4A 48%, #10263F 100%);
  border-bottom: 0; color: var(--on-dark); overflow: hidden;
}
.masthead .container { padding-block: 22px clamp(36px, 4vw, 56px); }
.masthead h1 { color: var(--white); margin-top: 16px; font-size: clamp(1.85rem, 1.35rem + 1.7vw, 2.55rem); line-height: 1.12; max-width: 20ch; }
.masthead-lead { margin-top: 14px; max-width: 52ch; font-size: 1.0625rem; line-height: 1.6; color: var(--on-dark); }
.masthead .crumbs a { color: #9FB6CF; }
.masthead .crumbs a:hover { color: var(--white); }
.masthead .crumbs [aria-current] { color: #CFE0F0; }
.masthead .crumbs li + li::before { color: rgba(255, 255, 255, 0.3); }

.mast-grid { display: grid; grid-template-columns: minmax(0, 0.84fr) minmax(0, 1.16fr); gap: clamp(28px, 4vw, 56px); align-items: center; }
.mast-actions { display: flex; flex-wrap: wrap; gap: 12px 16px; margin-top: 26px; }

.facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 28px; margin-top: 30px; max-width: 430px; }
.facts > div:nth-child(even) { padding-left: 28px; border-left: 1px solid rgba(255, 255, 255, 0.18); }
.facts dt { font-size: 0.78rem; color: #9FB6CF; }
.facts dd { margin-top: 3px; font-family: var(--font-head); font-weight: 600; font-size: 0.925rem; color: var(--white); }
/* One column below 1000px. The headline keeps a tight measure so it breaks
   into a strong shape; the paragraph takes the width it has, up to a readable
   line, rather than leaving half the row empty. */
@media (max-width: 1000px) {
  .mast-grid { grid-template-columns: 1fr; }
  .masthead h1 { max-width: 34ch; }
  .masthead-lead { max-width: min(100%, 64ch); }
}
@media (max-width: 420px) { .facts { grid-template-columns: 1fr; } .facts > div:nth-child(even) { padding-left: 0; border-left: 0; } }

/* ---- the phase machine ---- */
.pm { margin: 0; }
/* The window is Odoo's own, so it is light. Colours sampled from an Odoo 18
   screen: white ground, #2C646C headings, #BCDCF4 chart fill, #64A4EC lines,
   #449C54 for anything confirmed. The frame below it stays on the dark hero. */
.pm-screen {
  border-radius: 14px; overflow: hidden; background: #FFFFFF;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.65);
}
/* the screen only. A nested svg (the wordmark) keeps its own width and height,
   which a bare `.pm svg` rule would override and blow up to the full frame. */
.pm-screen > svg { display: block; width: 100%; height: auto; }

/* every piece eases between stages; nothing jumps */
.pm-screen svg [class] { transition: opacity .5s ease, transform .5s ease; }
@media (prefers-reduced-motion: reduce) { .pm-screen svg [class] { transition: none; } }

.pm .frame { fill: #FFFFFF; stroke: #E2E5E9; stroke-width: 1.5; }
.pm .sidebar-bg { fill: #F8F9FA; opacity: 0; }
.pm .frame-line { stroke: #E6E8EB; stroke-width: 1.5; }
.pm .dot { fill: #D2D6DB; }

.pm .wire { fill: none; stroke: #C7CDD4; stroke-width: 1.4; stroke-dasharray: 5 4; opacity: 0; }
.pm .fill { fill: #D9DEE4; opacity: 0; }
.pm .fill--dim { fill: #E8EBEF; }
.pm .fill--accent { fill: #BCDCF4; }
.pm .head-fill { fill: #2C646C; }
.pm .app-icon { fill: #E4ECFC; opacity: 0; }
.pm .sidebar-line, .pm .sidebar-bg, .pm .chart, .pm .people, .pm .live, .pm .care { opacity: 0; }
.pm .tick { opacity: 0; }
.pm .tick circle { fill: #449C54; }
.pm .tick path { stroke: #FFFFFF; }
.pm .chart-bg { fill: #FBFCFD; stroke: #ECEEF1; stroke-width: 1; }
.pm .bar { fill: #BCDCF4; opacity: 1; }
.pm .trend { stroke: #64A4EC; stroke-width: 2.4; stroke-linecap: round; }
.pm .person circle { fill: #E4ECFC; }
.pm .person .head { fill: #7FA6C9; }
.pm .live-dot { fill: #449C54; }
.pm .live-ring { fill: none; stroke: #449C54; stroke-width: 1.5; opacity: 0; }
.pm .care-seg { fill: rgba(44, 100, 108, 0.10); }
.pm .care-seg--open { fill: none; stroke: rgba(44, 100, 108, 0.34); stroke-width: 1.6; stroke-linejoin: round; }

/* stage 2: the wireframe */
.pm[data-stage="2"] .wire { opacity: 1; }
.pm[data-stage="2"] .app-icon { opacity: .5; }
.pm[data-stage="2"] .sidebar-line, .pm[data-stage="2"] .sidebar-bg { opacity: 1; }

/* stage 3 and on: real structure */
.pm[data-stage="3"] .fill, .pm[data-stage="4"] .fill, .pm[data-stage="5"] .fill,
.pm[data-stage="6"] .fill, .pm[data-stage="7"] .fill { opacity: 1; }
.pm[data-stage="3"] .app-icon, .pm[data-stage="4"] .app-icon, .pm[data-stage="5"] .app-icon,
.pm[data-stage="6"] .app-icon, .pm[data-stage="7"] .app-icon { opacity: 1; }
.pm[data-stage="3"] .sidebar-line, .pm[data-stage="4"] .sidebar-line, .pm[data-stage="5"] .sidebar-line,
.pm[data-stage="6"] .sidebar-line, .pm[data-stage="7"] .sidebar-line,
.pm[data-stage="3"] .sidebar-bg, .pm[data-stage="4"] .sidebar-bg, .pm[data-stage="5"] .sidebar-bg,
.pm[data-stage="6"] .sidebar-bg, .pm[data-stage="7"] .sidebar-bg { opacity: 1; }
.pm[data-stage="3"] .chart, .pm[data-stage="4"] .chart, .pm[data-stage="5"] .chart,
.pm[data-stage="6"] .chart, .pm[data-stage="7"] .chart { opacity: 1; }

/* stage 4: sign-off */
.pm[data-stage="4"] .tick, .pm[data-stage="5"] .tick,
.pm[data-stage="6"] .tick, .pm[data-stage="7"] .tick { opacity: 1; }

/* stage 5: the people who will use it */
.pm[data-stage="5"] .people, .pm[data-stage="6"] .people, .pm[data-stage="7"] .people { opacity: 1; }

/* stage 6: live */
.pm[data-stage="6"] .live, .pm[data-stage="7"] .live { opacity: 1; }
.pm[data-stage="6"] .app-icon, .pm[data-stage="7"] .app-icon { fill: #9CC6F0; }

/* stage 7: hypercare watching over it */
.pm[data-stage="7"] .care { opacity: 1; }

/* the one orchestrated motion: things arrive in sequence, not all at once */
@media (prefers-reduced-motion: no-preference) {
  .pm[data-stage="2"] .row .wire, .pm[data-stage="3"] .row .fill { transition-delay: calc(var(--i) * 70ms); }
  .pm .app-icon { transition-delay: calc(var(--i) * 45ms); }
  .pm .tick { transition-delay: calc(var(--i) * 90ms); }
  .pm .person { transition-delay: calc(var(--i) * 110ms); }
  .pm .bar { transition-delay: calc(var(--i) * 60ms); }
  .pm[data-stage="6"] .live-ring { animation: live-ping 2.4s ease-out infinite; opacity: 1; }
  .pm[data-stage="7"] .live-ring { animation: live-ping 2.4s ease-out infinite; opacity: 1; }
  .pm[data-stage="7"] .care-ring { animation: care 4s ease-in-out infinite; }
  .pm[data-stage="7"] .care-ring--2 { animation-delay: 2s; }
}
@keyframes live-ping { 0% { r: 5; opacity: .9; } 100% { r: 16; opacity: 0; } }
@keyframes care { 0%, 100% { transform: scale(.86); opacity: 0; } 50% { transform: scale(1); opacity: 1; } }
.pm .care-ring { transform-origin: 320px 200px; }

/* the phase track doubles as the control */
.pm-track { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-top: 18px; }
.pm-step { background: none; border: 0; padding: 0; cursor: pointer; display: grid; gap: 7px; justify-items: start; }
.pm-step-bar { display: block; width: 100%; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.18); transition: background-color .3s ease; }
.pm-step-no { font-family: var(--font-head); font-weight: 600; font-size: 0.8rem; color: #7E97B3; transition: color .3s ease; }
.pm-step:hover .pm-step-bar { background: rgba(255, 255, 255, 0.4); }
.pm-step[aria-current] .pm-step-bar { background: var(--blue); }
.pm-step[aria-current] .pm-step-no { color: var(--white); }
.pm-step.is-done .pm-step-bar { background: rgba(33, 150, 243, 0.5); }
.pm-step:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 3px; }

.pm-captions { position: relative; margin-top: 16px; min-height: 68px; }
.pm-caption {
  position: absolute; inset: 0; font-size: 0.95rem; line-height: 1.6; color: var(--on-dark);
  opacity: 0; transition: opacity .35s ease; max-width: 60ch;
}
.pm-caption strong { color: var(--white); font-family: var(--font-head); font-weight: 600; }
.pm-caption.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .pm-caption { transition: none; } }
@media (max-width: 560px) { .pm-captions { min-height: 92px; } .pm-step-no { font-size: 0.72rem; } }

/* Odoo wordmark in the workspace title bar. Monochrome white is the standard
   treatment on a dark background; swap in Odoo's own partner asset if they supply one. */
.pm .odoo-mark { opacity: 0; }
/* the wordmark is Odoo's plum, as it is on their own white chrome */
.pm .odoo-rest, .pm .odoo-lead { fill: #714B67; }
.pm[data-stage="1"] .odoo-mark { opacity: .3; }
.pm[data-stage="2"] .odoo-mark { opacity: .55; }
.pm[data-stage="3"] .odoo-mark, .pm[data-stage="4"] .odoo-mark, .pm[data-stage="5"] .odoo-mark,
.pm[data-stage="6"] .odoo-mark, .pm[data-stage="7"] .odoo-mark { opacity: 1; }

/* ============ Document ground and lifted panels ============
   The body sits on a soft neutral rather than stark white, and the two
   sections that carry the most weight lift off it: the phases on dark,
   echoing the hero, and the questions on white. */
.doc-wrap { background: #F4F6F8; }
.doc-sec { border-top: 1px solid #DFE4EA; }

.panel { border-radius: 16px; padding: clamp(26px, 3vw, 40px); }
.doc-sec--panel { border-top: 0; margin-block: clamp(32px, 4vw, 48px); }

.panel--light { background: var(--white); border: 1px solid #E3E8EE; }
/* A third panel, between the white one and the navy one. It exists for the
   logo wall: white cards need something other than white behind them, and a
   page only gets one dark anchor before the anchor stops being one. */
.panel--mist { background: var(--mist); border: 1px solid #DFE8F3; }
.panel--dark {
  background:
    radial-gradient(760px 340px at 88% 6%, rgba(33, 150, 243, 0.17), transparent 60%),
    linear-gradient(150deg, #0C2341 0%, #0F2A4A 55%, #10273F 100%);
  color: var(--on-dark);
}
.panel--dark > h2 { color: var(--white); }
.panel--dark > h2 + p { color: #A9C0D8; }

/* the ledger, inverted */
.panel--dark .ledger { border-bottom-color: rgba(255, 255, 255, 0.14); }
.panel--dark .phase-row { border-top-color: rgba(255, 255, 255, 0.14); }
.panel--dark .phase-row h3 { color: var(--white); }
.panel--dark .phase-no { color: var(--blue); }
.panel--dark .phase-facts dt { color: #8FA8C4; }
.panel--dark .phase-facts dd { color: #C9D6E6; }
.panel--dark .phase-facts .ph-get { color: var(--white); font-weight: 500; }

/* the proof cards read against the ground without a surface of their own */
.proof-where { color: #5B6B7C; }

@media (max-width: 1000px) { .doc-sec--panel { margin-inline: calc(var(--gutter) * -0.5); } }
@media (max-width: 620px) { .panel { border-radius: 12px; } }

/* ============ Phases as a journey ============
   A track across the page with seven stops. The line fills to the stop you are
   on, and that stop's detail opens beneath it. Behind it, one blurred scene per
   phase, cross-faded as you move along the track: texture, never a picture you
   are meant to read. The scrim holds every scene dark enough that the dimmest
   label on top still clears 4.5:1. */
/* ---- the photograph behind the section ----
   A different scene for each phase, blurred and duotoned into a light blue,
   cross-faded as you move along the track. No text sits on it: the heading and
   everything under it ride on one dark glass card, which is what lets the
   photograph stay light. */
.panel--scenes { position: relative; overflow: hidden; isolation: isolate; }
.panel--scenes > .phases-ui { position: relative; }

.phase-scenes { position: absolute; inset: 0; }
.phase-scene {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0; transition: opacity .55s ease;
}
.phase-scene.is-on { opacity: 1; }
/* a light wash only: enough to tie the seven scenes together and keep the
   edges from glaring, not enough to turn the photograph back into navy */
.phase-scrim {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 45%, transparent 38%, rgba(8, 26, 50, 0.34) 100%),
    linear-gradient(118deg, rgba(10, 32, 62, 0.26) 0%, rgba(10, 32, 62, 0.10) 52%, rgba(12, 38, 72, 0.22) 100%);
}
@media (prefers-reduced-motion: reduce) { .phase-scene { transition: none; } }

.phases-ui { margin-top: clamp(30px, 3.5vw, 44px); }
/* The card is frosted glass over the photograph, and because the photograph is
   light the type on it is dark. This is the one light section on the page. */
.panel--scenes { padding: clamp(22px, 3.4vw, 48px); }
.panel--scenes .phases-ui {
  margin-top: 0; background: rgba(250, 252, 255, 0.90);
  border: 1px solid rgba(255, 255, 255, 0.85); border-radius: 18px;
  padding: clamp(24px, 3vw, 40px);
  box-shadow: 0 2px 0 rgba(255, 255, 255, 0.5) inset, 0 30px 70px rgba(6, 26, 52, 0.22);
}
@supports (backdrop-filter: blur(1px)) {
  .panel--scenes .phases-ui {
    background: rgba(248, 251, 255, 0.70); backdrop-filter: blur(26px) saturate(1.4);
  }
}
.panel--scenes .phases-ui > h2 { color: var(--ink); max-width: 24ch; }
.panel--scenes .phases-lead {
  margin-top: 14px; max-width: 64ch; line-height: 1.7; color: #35475B;
}
.panel--scenes .track { margin-top: clamp(30px, 3.5vw, 44px); }

.panel--scenes .track-line { background: rgba(15, 42, 74, 0.16); }
.panel--scenes .stop-dot { background: #C6D7E7; border-color: rgba(15, 42, 74, 0.26); }
.panel--scenes .stop.is-done .stop-dot { background: var(--action); border-color: var(--action); }
.panel--scenes .stop[aria-selected="true"] .stop-dot {
  background: var(--white); border-color: var(--action);
  box-shadow: 0 0 0 5px rgba(21, 101, 192, 0.18);
}
.panel--scenes .stop-label, .panel--scenes .stop-no { color: #2E435A; }
.panel--scenes .stop.is-done .stop-label { color: #27405C; }
.panel--scenes .stop:hover .stop-label { color: var(--ink); }
.panel--scenes .stop:hover .stop-dot { border-color: rgba(15, 42, 74, 0.5); }
.panel--scenes .stop[aria-selected="true"] .stop-label,
.panel--scenes .stop[aria-selected="true"] .stop-no { color: var(--ink); }

.panel--scenes .phase-panel {
  background: rgba(255, 255, 255, 0.52); border-color: rgba(15, 42, 74, 0.11);
}
.panel--scenes .phase-panel-step { color: #44586D; }
.panel--scenes .phase-panel h3 { color: var(--ink); }
.panel--scenes .phase-facts dt { color: #0E4F9C; border-bottom-color: rgba(15, 42, 74, 0.16); }
.panel--scenes .phase-facts dd { color: #37485C; }
.panel--scenes .phase-facts .ph-get dt { color: #09564E; border-bottom-color: rgba(11, 110, 99, 0.34); }
.panel--scenes .phase-facts .ph-get dd { color: var(--ink); font-weight: 600; }
.panel--scenes .phase-step { color: var(--ink); border-color: rgba(15, 42, 74, 0.24); }
.panel--scenes .phase-step:hover:not([disabled]) {
  background: rgba(15, 42, 74, 0.06); border-color: rgba(15, 42, 74, 0.42);
}
.panel--scenes .phase-step--go { color: var(--white); border-color: var(--action); }

.track {
  position: relative; display: grid; grid-template-columns: repeat(var(--stops, 7), 1fr);
  padding-top: 4px;
}
.track-line, .track-fill {
  position: absolute; top: 12px; height: 2px; border-radius: 2px;
  left: calc(50% / var(--stops, 7));
}
.track-line { right: calc(50% / var(--stops, 7)); background: rgba(255, 255, 255, 0.18); }
.track-fill {
  width: calc((100% - (100% / var(--stops, 7))) * var(--p, 0));
  background: linear-gradient(90deg, var(--blue), #4FB2F7);
  transition: width .5s cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-reduced-motion: reduce) { .track-fill { transition: none; } }

.stop {
  position: relative; z-index: 1; background: none; border: 0; padding: 0 4px;
  display: grid; justify-items: center; gap: 12px; cursor: pointer;
}
.stop-dot {
  width: 14px; height: 14px; border-radius: 50%; margin-top: 6px;
  background: #16304E; border: 2px solid rgba(255, 255, 255, 0.3);
  transition: background-color .3s ease, border-color .3s ease, transform .3s ease, box-shadow .3s ease;
}
.stop.is-done .stop-dot { background: var(--blue); border-color: var(--blue); }
.stop[aria-selected="true"] .stop-dot {
  background: var(--white); border-color: var(--blue); transform: scale(1.5);
  box-shadow: 0 0 0 5px rgba(33, 150, 243, 0.25);
}
.stop-label {
  font-family: var(--font-head); font-weight: 500; font-size: 0.85rem; line-height: 1.25;
  color: #93AEC9; text-align: center; transition: color .3s ease;
}
.stop-no { display: none; font-family: var(--font-head); font-weight: 600; font-size: 0.82rem; color: #93AEC9; }
.stop:hover .stop-label { color: var(--white); }
.stop:hover .stop-dot { border-color: rgba(255, 255, 255, 0.65); }
.stop.is-done .stop-label { color: #BBD0E4; }
.stop[aria-selected="true"] .stop-label,
.stop[aria-selected="true"] .stop-no { color: var(--white); font-weight: 600; }
.stop:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 6px; }
@media (prefers-reduced-motion: reduce) { .stop-dot { transition: none; } }

@media (max-width: 680px) {
  .stop-label { display: none; }
  .stop-no { display: block; }
}

.phase-stage { margin-top: clamp(26px, 3vw, 34px); min-height: 268px; }
.phase-panel {
  background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px; padding: clamp(22px, 2.4vw, 30px);
}
.phase-panel[hidden] { display: none; }
.phase-panel-step {
  font-size: 0.78rem; letter-spacing: 0.06em; text-transform: uppercase;
  font-family: var(--font-head); font-weight: 600; color: #A3BAD2;
}
.phase-panel h3 { margin-top: 5px; font-size: clamp(1.25rem, 2vw, 1.5rem); color: var(--white); }

.phase-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px 32px; margin-top: 22px; }
.phase-facts dt {
  font-family: var(--font-head); font-weight: 600; font-size: 0.85rem; color: var(--blue);
  padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
.phase-facts dd { margin-top: 12px; font-size: 0.975rem; line-height: 1.6; color: #C9D6E6; }
.phase-facts .ph-get dt { color: #2FC08A; border-bottom-color: rgba(47, 192, 138, 0.35); }
.phase-facts .ph-get dd { color: var(--white); font-weight: 500; }

@media (prefers-reduced-motion: no-preference) {
  .phase-panel:not([hidden]) { animation: phase-in .32s ease both; }
}
@keyframes phase-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.phase-nav { display: flex; gap: 12px; margin-top: 18px; }
.phase-step {
  cursor: pointer; min-height: 42px; padding: 10px 20px; border-radius: 6px;
  font-family: var(--font-head); font-weight: 600; font-size: 0.9rem;
  background: none; color: var(--white); border: 1px solid rgba(255, 255, 255, 0.26);
  transition: background-color .15s ease, border-color .15s ease;
}
.phase-step:hover:not([disabled]) { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.45); }
.phase-step--go { background: var(--action); border-color: var(--action); }
.phase-step--go:hover:not([disabled]) { background: var(--action-hover); border-color: var(--action-hover); }
.phase-step[disabled] { opacity: .35; cursor: default; }
.phase-step:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

@media (max-width: 1000px) { .phase-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 700px) { .phase-facts { grid-template-columns: 1fr; gap: 20px; } .phase-stage { min-height: 0; } }
@media (max-width: 520px) { .phase-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }


/* ============ Odoo Development ============ */

/* The stack, drawn as a cross-section rather than as four cards.
   The strata sit flush against each other and darken with depth, so the block
   reads as one system seen edge-on. The continuous rail down the left edge is
   the only loud thing here: it carries the depth, which is the whole point of
   the section, and everything else stays quiet. No numbers, because these
   layers run at the same time and are not a sequence. */
.stack { margin: 0; display: grid; gap: clamp(14px, 1.6vw, 20px); }

.strata {
  list-style: none; position: relative; overflow: hidden;
  border: 1px solid #D4E1EE; border-radius: 16px;
  box-shadow: 0 26px 50px -34px rgba(15, 42, 74, 0.32);
}
.strata::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 6px;
  background: linear-gradient(180deg, #8CC7F7 0%, #4A94DA 34%, #1E5FA8 68%, #0F2A4A 100%);
}

.stratum {
  display: grid; grid-template-columns: minmax(0, 1fr) 250px;
  gap: 14px 34px; align-items: start;
  padding: clamp(17px, 1.9vw, 23px) clamp(20px, 2.2vw, 28px)
           clamp(17px, 1.9vw, 23px) clamp(26px, 2.8vw, 36px);
}
/* surface at the top, data at the bottom */
.stratum:nth-child(1) { background: #FFFFFF; }
.stratum:nth-child(2) { background: #F1F7FC; }
.stratum:nth-child(3) { background: #E4EFF8; }
.stratum:nth-child(4) { background: #D5E6F4; }

.stratum-say h3 {
  font-family: var(--font-head); font-weight: 600; font-size: 0.98rem;
  color: var(--ink); letter-spacing: -0.005em;
}
.stratum-say p {
  margin-top: 5px; font-size: 0.875rem; line-height: 1.55; color: #4A5F76;
  max-width: 54ch;
}

/* Not a layer. It is the route the work takes to reach you, so it sits
   outside the block, is drawn as a path rather than as ground, and carries
   the other half of the palette: the strata are blue because they are the
   system, this is green because it is the thing going live. */
.ship {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: minmax(0, 1fr) 250px;
  gap: 14px 34px; align-items: center;
  padding: clamp(15px, 1.7vw, 20px) clamp(20px, 2.2vw, 28px)
           clamp(15px, 1.7vw, 20px) clamp(26px, 2.8vw, 36px);
  border: 1px dashed #9ECCB4; border-left: 0; border-radius: 14px;
  background: #ECF6F0;
}
/* The same rail as the block above, in the band's own colour. Solid rather
   than graded: the strata rail shows depth increasing, and this band has no
   depth, it is a route. Pitched to the same darkness as the navy the other
   rail ends on, so the two read as a pair. */
.ship::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 6px;
  background: #0E3A26;
}
.ship .stratum-say p { color: #3F5C4C; }
.ship .lang { border-color: #CFE5DA; }

.langs { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.lang {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px; border-radius: 999px;
  background: var(--white); border: 1px solid #D5E1ED;
  box-shadow: 0 1px 2px rgba(15, 42, 74, 0.05), 0 6px 14px -10px rgba(15, 42, 74, 0.3);
  font-family: var(--font-head); font-weight: 500; font-size: 0.78rem; color: #2E4458;
  white-space: nowrap;
}
/* Height is fixed, width follows, so a wide wordmark stays legible instead of
   being squashed into a square box. */
.lang img { height: 17px; width: auto; max-width: 58px; display: block; }

/* The block lands, then the logos settle onto it in one diagonal pass, and
   then everything is still. One moment, not ten looping ones: these chips sit
   beside body copy people are trying to read.

   The hiding is keyed off `is-armed`, which the script adds, so the chips are
   never invisible on a page where the script did not run. The animation fills
   backwards rather than both, so once it has finished the chip goes back to
   its own styles and the hover below is free to move it. */
@media (prefers-reduced-motion: no-preference) {
  .stack.is-armed { opacity: 0; transform: translateY(10px); }
  .stack.is-armed.is-in {
    opacity: 1; transform: none;
    transition: opacity .5s ease, transform .5s cubic-bezier(.3, .8, .4, 1);
  }
  .stack.is-armed:not(.is-in) .lang { opacity: 0; }
  .stack.is-armed.is-in .lang {
    animation: chip-in .42s cubic-bezier(.34, 1.42, .52, 1) backwards;
    animation-delay: calc(300ms + var(--i) * 45ms);
  }
}
@keyframes chip-in {
  from { opacity: 0; transform: scale(.82) translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* Hover, only where a pointer can actually hover. On a touch screen this
   would stick on after a tap. any-hover rather than hover, so a desktop with
   a touchscreen still gets it. The logo lifts further than the chip does, so
   the mark is what you notice rather than the pill. */
@media (any-hover: hover) {
  .lang {
    transition: transform .2s cubic-bezier(.34, 1.36, .52, 1),
                box-shadow .2s ease, border-color .2s ease;
  }
  .lang:hover {
    transform: translateY(-3px);
    border-color: #A7C7E8;
    box-shadow: 0 2px 4px rgba(15, 42, 74, 0.07), 0 16px 24px -13px rgba(15, 42, 74, 0.45);
  }
  .lang img { transition: transform .24s cubic-bezier(.34, 1.5, .52, 1); }
  .lang:hover img { transform: scale(1.14); }
}
@media (prefers-reduced-motion: reduce) {
  .lang, .lang img { transition: none; }
  .lang:hover { transform: none; }
  .lang:hover img { transform: none; }
}

@media (max-width: 860px) {
  .stratum, .ship { grid-template-columns: 1fr; gap: 12px; }
  .stratum-say p { max-width: none; }
}

/* the upgrade rules, on the dark panel */
/* The rules the firm holds itself to. Each one is ticked rather than ruled
   off: the dividers were doing nothing except repeating the shape of the
   section above, and a tick says what the list actually is. */
.rules {
  list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(26px, 3vw, 34px) clamp(36px, 4vw, 56px);
  margin-top: clamp(30px, 3.4vw, 40px); align-items: start;
}
.rule { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 5px 13px; }
.tk {
  grid-row: span 2; margin-top: 2px; width: 20px; height: 20px; flex: none;
  fill: none; stroke: #4ADE9B; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .22s cubic-bezier(.34, 1.4, .52, 1);
}
.tk .tk-disc { fill: rgba(74, 222, 155, 0.13); stroke: rgba(74, 222, 155, 0.4); stroke-width: 1.2; }
.rule h3 {
  align-self: center; font-family: var(--font-head); font-weight: 600;
  font-size: 0.975rem; color: var(--white);
}
.rule p { font-size: 0.925rem; line-height: 1.6; color: #B6C9DD; max-width: 46ch; }

/* The same commitment list on a light panel. The defaults above are written
   for the navy panel, because Development uses them there; these override only
   the colours, so one list works on either background. The tick keeps its
   green, darkened to hold against a pale panel rather than a dark one. */
.panel--mist .rule h3 { color: var(--ink); }
.panel--mist .rule p { color: var(--graphite); }
.panel--mist .sec-lead { color: var(--graphite); }
.panel--mist .tk { stroke: #1C8A57; }
.panel--mist .tk .tk-disc { fill: rgba(28, 138, 87, 0.1); stroke: rgba(28, 138, 87, 0.35); }

@media (any-hover: hover) { .rule:hover .tk { transform: scale(1.12); } }
@media (prefers-reduced-motion: reduce) {
  .tk { transition: none; }
  .rule:hover .tk { transform: none; }
}
@media (max-width: 760px) {
  .rules { grid-template-columns: 1fr; gap: 24px; }
  .rule p { max-width: 62ch; }   /* one column is wide: keep the line readable */
}

/* how a build runs: numbered, because the order is the point */


/* ---- the hero: a module assembling itself ---- */
/* A light window on the dark masthead, the same way the Implementation hero
   carries a light Odoo window: the thing being shown is a light editor, so
   the card is light and the page behind it is not. */
.modtree {
  margin: 0; border-radius: 14px; overflow: hidden;
  background: #F4F6F9;
  border: 1px solid rgba(255, 255, 255, 0.28);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.55);
}
.modtree-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 13px 16px; background: #E9EDF2; border-bottom: 1px solid #DCE3EA;
}
.modtree-dot { width: 9px; height: 9px; border-radius: 50%; background: #C2CCD7; }
.modtree-path {
  margin-left: 10px; font-family: var(--font-mono); font-size: 0.76rem;
  color: #51657B; letter-spacing: 0.01em;
}
.modtree-files { list-style: none; padding: 14px 16px 6px; display: grid; gap: 1px; }
.f {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 8px 4px calc(10px + var(--d) * 20px); border-radius: 5px;
  font-family: var(--font-mono); font-size: 0.8rem; line-height: 1.5;
  color: #27384B; white-space: nowrap;
  opacity: 0; transform: translateX(-8px);
  transition: opacity .34s ease, transform .34s ease;
}
.f.is-in { opacity: 1; transform: none; }
/* a folder is the structure, a file is the work */
.f--dir { color: #566A80; }
.f--dir .f-name::before { content: ''; display: inline-block; width: 11px; height: 9px;
  margin-right: 8px; border-radius: 2px; background: rgba(86, 106, 128, 0.6); vertical-align: 1px; }
.f-name { overflow: hidden; text-overflow: ellipsis; }
.f-lang {
  margin-left: auto; flex: none; padding: 2px 9px; border-radius: 999px;
  font-family: var(--font-head); font-weight: 500; font-size: 0.68rem;
  background: #E4F0FB; color: #15558F; border: 1px solid #CBE0F3;
}
.f--py .f-lang { background: #E4F0FB; color: #15558F; border-color: #CBE0F3; }
.f--xml .f-lang { background: #FAEFDE; color: #7E5210; border-color: #EFDBBA; }
.f--csv .f-lang { background: #E0F2E9; color: #146041; border-color: #C5E5D4; }
.f--js .f-lang { background: #F2E6EF; color: #70395F; border-color: #E3CFDD; }
.f--scss .f-lang { background: #F2E6EF; color: #70395F; border-color: #E3CFDD; }

.modtree-done {
  margin: 4px 16px 16px; padding-top: 12px; border-top: 1px solid #DCE3EA;
  font-size: 0.85rem; color: #4E6279;
  opacity: 0; transform: translateY(4px); transition: opacity .4s ease, transform .4s ease;
}
.modtree-done.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .f, .modtree-done { transition: none; }
}
@media (max-width: 520px) {
  .f { font-size: 0.74rem; padding-left: calc(8px + var(--d) * 14px); }
  .f-lang { font-size: 0.64rem; padding: 2px 7px; }
}

/* ---- who writes it: the claim, with the office beside it ---- */
.who {
  display: grid; grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
  gap: clamp(24px, 3vw, 44px); align-items: center;
}
.who-say p { color: #41566C; line-height: 1.66; }
.who-say p + p { margin-top: 14px; }
@media (max-width: 1180px) { .who { grid-template-columns: 1fr; } }
.who-say strong {
  display: inline-block; margin-left: 2px; padding: 1px 7px; border-radius: 4px;
  background: #FFF3D6; border: 1px solid #EBD199;
  font-family: var(--font-head); font-weight: 600; font-size: 0.74rem;
  letter-spacing: 0.02em; color: #7A4E06; vertical-align: 2px;
}
/* One photograph at a time, stepped with the arrows. Every frame holds the
   ratio the photographs are cut to, so the crop never reaches the sign on the
   wall or the people at the left edge. The count beside the arrows is there so
   a visitor can see there is more than one without having to click to find out. */
.shots-wrap { margin: 0; }
.shots {
  display: grid; grid-auto-flow: column; grid-auto-columns: 100%;
  gap: 16px;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: none; -ms-overflow-style: none;
}
.shots::-webkit-scrollbar { display: none; }
.shots:focus-visible { outline: 2px solid var(--action); outline-offset: 4px; }
.shots--one { margin: 0; }
.shot { margin: 0; scroll-snap-align: start; }
.shot img {
  display: block; width: 100%; height: auto; aspect-ratio: 1.42;
  object-fit: cover; object-position: 50% 50%;
  border-radius: 14px; border: 1px solid #DFE6ED;
}
.shots-nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; margin-top: 14px;
}
.shots-btns { display: flex; gap: 10px; }
.shots-count {
  font-family: var(--font-head); font-weight: 500; font-size: 0.82rem;
  color: #5B7088; letter-spacing: 0.01em;
}
/* Nothing to step through, nothing to show. */
.shots[data-scrollable="0"] ~ .shots-nav { display: none; }
@media (prefers-reduced-motion: reduce) { .shots { scroll-behavior: auto; } }


/* No photograph supplied yet. Visible on purpose: this must not ship empty. */
.shot--todo {
  display: grid; place-items: center; aspect-ratio: 16 / 10; border-radius: 14px;
  background: repeating-linear-gradient(135deg, #F1F5F9 0 12px, #E9EFF5 12px 24px);
  border: 1px dashed #B9C8D7; text-align: center; padding: 20px;
}
.shot--todo p {
  font-family: var(--font-head); font-weight: 600; font-size: 0.92rem; color: #4A6179;
}
.shot--todo span {
  display: inline-block; margin-top: 7px; font-family: var(--font-mono);
  font-weight: 400; font-size: 0.76rem; color: #6D8299;
}

/* ---- what we build: the seven marks ---- */
/* The marks are arrangements of the same rounded square that marks a folder
   in the hero tree, so the set reads as this site's own rather than a stock
   icon pack. They carry no meaning the heading does not already carry, which
   is why they are quiet and monochrome. */
.made-grid {
  list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 36px) clamp(32px, 4vw, 56px);
  margin-top: clamp(26px, 3vw, 34px);
  align-items: start;   /* otherwise a long item in one column stretches its
                           neighbour and opens a gap under that heading */
}
.made {
  display: grid; grid-template-columns: 42px minmax(0, 1fr);
  gap: 4px 16px; align-items: start;
}
/* The mark sits on a tile of its own so it has some weight against the text.
   Aligned to the first line of the heading rather than centred on the whole
   block, which is what made the rows drift out of line with each other. */
.mk {
  grid-row: span 2; box-sizing: content-box;
  width: 24px; height: 24px; padding: 9px; border-radius: 12px;
  background: #E7F1FA;
  color: #2F6FB5; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  transition: background-color .22s ease, color .22s ease, transform .22s cubic-bezier(.34, 1.36, .52, 1);
}
.mk .mk-fill { fill: #BBD8F3; }
.mk .mk-card { fill: #E7F1FA; }
.made h3 {
  min-height: 42px; display: flex; align-items: center;
  font-family: var(--font-head); font-weight: 600; font-size: 1rem; color: var(--ink);
}
.made p { font-size: 0.95rem; line-height: 1.6; color: #4A5F76; }

@media (any-hover: hover) {
  .made:hover .mk { background: #D8E9F8; color: #1F5897; transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .mk { transition: none; }
  .made:hover .mk { transform: none; }
}

@media (max-width: 760px) {
  .made-grid { grid-template-columns: 1fr; gap: 22px; }
}

/* ============ the Integration hero: three records crossing ============
   A light panel on the dark masthead, like the form view on Customization, so
   the two pages feel like the same site. Inside it, three transfers running
   one after another on a single seven second loop.

   Every timing below is a percentage of that one loop rather than a delay on
   a shorter animation. Delays drift against each other over a few minutes and
   the retry stops lining up with the row it belongs to; percentages of a
   shared duration cannot. Change the duration, not the percentages. */
.sync {
  margin: 0; padding: clamp(16px, 1.6vw, 22px); border-radius: 14px;
  background: #FFFFFF; border: 1px solid rgba(255, 255, 255, 0.28);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.55);
  --sy-dur: 7s;
}
.sy-head, .sy-row {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: minmax(0, 1fr) minmax(34px, 0.62fr) minmax(0, 1fr) 72px;
}
.sy-head { margin-bottom: 12px; }
.sy-end {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: #6D8299;
}
.sy-end--odoo { grid-column: 3; color: #7A4C6E; }

.sy-rows { list-style: none; display: grid; gap: 9px; }
.sy-src, .sy-dest {
  min-width: 0; padding: 8px 11px; border-radius: 8px;
  font-family: var(--font-mono); font-size: 0.76rem; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sy-src { background: #F1F4F8; color: #42566C; border: 1px solid #E1E7EE; }
.sy-dest { background: #F7F1F5; color: #6C4460; border: 1px solid #ECDFE7; }

.sy-track { position: relative; height: 2px; background: #E1E7EE; border-radius: 2px; }
.sy-dot {
  position: absolute; top: 50%; left: 0; width: 7px; height: 7px; margin-top: -3.5px;
  border-radius: 50%; background: var(--action); opacity: 0;
}

/* The status slot holds both chips stacked, so the row never changes height
   when one swaps for the other. */
.sy-states { position: relative; min-height: 22px; }
.sy-state {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; border-radius: 999px; font-size: 0.68rem;
  font-weight: 600; letter-spacing: 0.02em;
}
.sy-state--ok { background: #E6F3EC; color: #1C6B45; }
.sy-state--bad { background: #FBF0DC; color: #8A5B06; opacity: 0; }
.sy-foot {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid #EDF1F5;
  font-size: 0.78rem; color: #6D8299;
}

/* Until the script runs, the panel sits in its finished state: everything
   synced, no dots. That way a reader with no JavaScript sees the outcome
   rather than an empty diagram. */
.sync.is-armed .sy-state--ok { opacity: 0; }

/* The animations are switched on by no-preference rather than switched off by
   reduce. Turning them off afterwards needs a selector at least as specific as
   the ones that turned them on, and these carry five classes and an
   nth-child, so the override loses and the panel sits frozen on frame zero
   with every chip hidden. Opting in cannot fail that way. */
@media (prefers-reduced-motion: no-preference) {
  .sync.is-armed.is-in .sy-row:nth-child(1) .sy-dot { animation: sy-go-1 var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(2) .sy-dot { animation: sy-go-2 var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(3) .sy-dot { animation: sy-go-3 var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(1) .sy-state--ok { animation: sy-ok-1 var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(2) .sy-state--ok { animation: sy-ok-2 var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(2) .sy-state--bad { animation: sy-bad var(--sy-dur) linear infinite; }
  .sync.is-armed.is-in .sy-row:nth-child(3) .sy-state--ok { animation: sy-ok-3 var(--sy-dur) linear infinite; }
}

@keyframes sy-go-1 {
  0%, 2%    { left: 0; opacity: 0; }
  4%        { left: 2%; opacity: 1; }
  19%       { left: calc(100% - 7px); opacity: 1; }
  21%, 100% { left: calc(100% - 7px); opacity: 0; }
}
/* The second one stops short, gives up, waits, and goes again from the start.
   The pause is the point: it is the only part of this picture that says
   anything a competitor's diagram does not. */
@keyframes sy-go-2 {
  0%, 25%   { left: 0; opacity: 0; }
  27%       { left: 2%; opacity: 1; background: var(--action); }
  36%       { left: 66%; opacity: 1; background: var(--action); }
  38%, 44%  { left: 66%; opacity: 1; background: #C9962E; }
  46%, 50%  { left: 66%; opacity: 0; background: #C9962E; }
  52%       { left: 2%; opacity: 1; background: var(--action); }
  67%       { left: calc(100% - 7px); opacity: 1; }
  69%, 100% { left: calc(100% - 7px); opacity: 0; }
}
@keyframes sy-go-3 {
  0%, 73%   { left: 0; opacity: 0; }
  75%       { left: 2%; opacity: 1; }
  88%       { left: calc(100% - 7px); opacity: 1; }
  90%, 100% { left: calc(100% - 7px); opacity: 0; }
}
@keyframes sy-ok-1 { 0%, 19% { opacity: 0; } 21%, 100% { opacity: 1; } }
@keyframes sy-bad  { 0%, 37% { opacity: 0; } 39%, 50% { opacity: 1; } 52%, 100% { opacity: 0; } }
@keyframes sy-ok-2 { 0%, 67% { opacity: 0; } 69%, 100% { opacity: 1; } }
@keyframes sy-ok-3 { 0%, 88% { opacity: 0; } 90%, 100% { opacity: 1; } }

/* Still, the panel shows its outcome: three records across, all landed. */
@media (prefers-reduced-motion: reduce) {
  .sync.is-armed .sy-state--ok { opacity: 1; }
  .sync .sy-dot, .sync .sy-state--bad { display: none; }
}
@media (max-width: 420px) {
  .sy-head, .sy-row { grid-template-columns: minmax(0, 1fr) 26px minmax(0, 1fr) 62px; gap: 7px; }
  .sy-src, .sy-dest { font-size: 0.7rem; padding: 7px 8px; }
}

/* ---- contact ----
   The page has one job, so the calendar is the hero object. The headline and
   the live dial share the top of the hero; the calendar runs full width under
   them so Cal gets its wide booker, and it overlaps into the next section so
   the hero's ground is not a flat field with a box in it. The one memorable
   thing is the dial: the brand ring as a 24-hour clock with the clients on it.
   Everything after the hero is quiet on purpose. */
.chero {
  --cal-overlap: 140px;
  position: relative; display: flow-root;   /* so the card's negative margin shortens the hero instead of collapsing through it */
  background: var(--ink); color: var(--on-dark);
  padding-block: 22px 0;
}
.chero .container { position: relative; }
.chero .crumbs a { color: #9FB6CF; }
.chero .crumbs a:hover { color: var(--white); }
.chero .crumbs [aria-current] { color: #CFE0F0; }
.chero .crumbs li + li::before { color: rgba(255, 255, 255, 0.3); }

.chero-grid {
  display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(24px, 3vw, 48px); align-items: center; margin-top: 26px;
}
.chero h1 {
  color: var(--white); font-size: clamp(2.2rem, 1.45rem + 2.5vw, 3.35rem);
  line-height: 1.06; letter-spacing: -0.015em; max-width: 12ch;
}
.chero-lead {
  margin-top: 22px; font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.175rem);
  line-height: 1.6; max-width: 44ch; text-wrap: pretty;
}
.chero-facts { list-style: none; margin-top: 30px; display: grid; gap: 14px; }
.chero-facts li {
  display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 12px; align-items: start;
  font-family: var(--font-head); font-weight: 500; font-size: 1rem; line-height: 1.45; color: var(--white);
  text-wrap: pretty;
}
.chero-facts .tk { grid-row: auto; margin-top: 1px; }
.chero-alt { margin-top: 30px; font-size: 0.95rem; color: #9FB6CF; }
.chero-alt a { color: var(--white); }

/* The dial. Lit arc is daytime, a filled dot is a city in daytime, a ring is
   one at night, so the state is a shape and not only a colour. */
.dial-wrap { margin: 0; min-width: 0; position: relative; }
/* A soft pool of light behind the dial, so it sits in the navy as a lit
   object rather than a line drawing. Done in CSS, not an SVG gradient: the
   review bundle renames ids, and a gradient is referenced by id. */
.dial-wrap::before {
  content: ""; position: absolute; left: 50%; top: 48%; width: 92%; aspect-ratio: 1;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(33, 150, 243, 0.22) 0%, rgba(33, 150, 243, 0.08) 42%, rgba(33, 150, 243, 0) 68%);
}
.dial { position: relative; width: 100%; height: auto; display: block; overflow: visible; }
.dial-face { fill: rgba(255, 255, 255, 0.035); }
.dial-base { fill: none; stroke: rgba(255, 255, 255, 0.16); stroke-width: 18; }
.dial-day {
  fill: none; stroke: var(--blue); stroke-width: 18; stroke-dasharray: 13 11; stroke-dashoffset: -7;
  filter: drop-shadow(0 0 14px rgba(33, 150, 243, 0.55));
}
.dial-ticks line { stroke: rgba(255, 255, 255, 0.34); stroke-width: 1.6; }
.dial-hours text { font-family: var(--font-body); font-size: 15px; fill: #9FB6CF; text-anchor: middle; font-variant-numeric: tabular-nums; }
.dial-centre text { text-anchor: middle; }
.dial-centre-kicker { font-family: var(--font-body); font-size: 19px; fill: #9FB6CF; }
.dial-centre-time { font-family: var(--font-head); font-weight: 600; font-size: 72px; fill: var(--white); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.dial-centre-sub { font-family: var(--font-body); font-size: 20px; fill: #8CC7F7; }
.dial-lead { stroke: rgba(255, 255, 255, 0.28); stroke-width: 1.4; }
.dial-dot { fill: var(--blue); stroke: var(--ink); stroke-width: 3.5; }
.dial-glow { fill: rgba(33, 150, 243, 0.3); }
.dial-mark.is-night .dial-dot { fill: var(--ink); stroke: #7F93AD; stroke-width: 2.5; }
.dial-mark.is-night .dial-glow { display: none; }
.dial-mark--us .dial-name { fill: #8CC7F7; }
.dial-mark.is-you .dial-dot { fill: var(--white); stroke: var(--ink); }
.dial-mark.is-you .dial-glow { fill: rgba(255, 255, 255, 0.22); }
.dial-label { font-family: var(--font-body); font-size: 20px; fill: var(--white); }
.dial-name { font-weight: 600; }
.dial-time { fill: #C9D6E6; font-variant-numeric: tabular-nums; }
.dial-mark.is-night .dial-label { fill: #B9C8DA; }
.dial-mark.is-night .dial-time { fill: #93A6BD; }
.dial-key {
  margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center;
  font-size: 0.85rem; color: #9FB6CF; justify-content: center;
}
.dial-key span { display: inline-flex; align-items: center; gap: 8px; }
.dial-key i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.dial-key-day { background: var(--blue); }
.dial-key-night { border: 2px solid #7F93AD; }
.dial-key-note { flex-basis: 100%; justify-content: center; }
/* Phones: the labels would be too small to read on the dial, so the names
   and times move to a list beneath it and the dial grows into the room the
   labels were keeping. */
.dial-list { display: none; }
@media (max-width: 700px) {
  .dial-label, .dial-lead { display: none; }
  .dial-wrap { overflow: hidden; }
  .dial { width: 150%; margin-left: -25%; }
  .dial-list {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px;
    list-style: none; margin-top: 4px; font-size: 0.95rem; color: var(--white);
  }
  .dial-list li { display: flex; align-items: baseline; gap: 8px; }
  .dial-list li i { width: 10px; height: 10px; border-radius: 50%; flex: none; align-self: center; }
  .dial-list li b { font-weight: 600; }
  .dial-list li span { color: #C9D6E6; font-variant-numeric: tabular-nums; }
  .dial-list li.is-night { color: #B9C8DA; }
  .dial-list li.is-night span { color: #93A6BD; }
  .dial-key-note { display: none; }
}

/* The calendar as an object: full width, white, with real depth, and it
   overlaps the next section so the hero and the page meet at the card. */
.chero-card {
  position: relative; z-index: 2;
  margin-top: clamp(40px, 5vw, 64px); margin-bottom: calc(-1 * var(--cal-overlap));
  background: var(--white); color: var(--ink); border-radius: 18px;
  padding: 16px 16px 14px;
  box-shadow: 0 32px 90px rgba(2, 12, 28, 0.35), 0 1px 0 rgba(255, 255, 255, 0.35) inset;
}
.chero-card-title { font-size: 1rem; font-weight: 600; color: var(--ink); padding: 4px 6px 14px; }
/* Cal's own div is width:100%;height:100%;overflow:scroll. A percentage
   height against a parent with no height resolves to zero, so an untouched
   paste renders nothing. Their frame also resizes itself to its content, so
   the right override is a floor and no inner scrollbar, not a fixed height. */
[id$="my-cal-inline-odoo-consultation"] {
  min-height: 640px; height: auto !important; overflow: visible !important;
  background: var(--white); border-radius: 12px;
}
/* Once Cal's frame is in, it sets its own height, and the floor would only
   add white space under it. No border either: their frame ends with padding
   of its own, and a box drawn round it only made that padding visible. */
[id$="my-cal-inline-odoo-consultation"]:has(iframe) { min-height: 0; }
/* Always visible, quietly. Cal is a third party on someone else's network, so
   there is always a route to the booking page that does not depend on it. */
.cal-fallback { margin: 2px 6px 0; font-size: 0.9rem; color: var(--graphite); }
/* The section after the hero makes room for the card's overlap. Matched by
   adjacency, never by id (see above). */
.chero + .section { padding-top: calc(140px + clamp(40px, 5vw, 64px)); }

/* Only ever seen in the single-file preview, never on the served site. */
.cal-note {
  padding: clamp(24px, 3vw, 34px); background: #FDF6E7;
  border: 1px dashed #D7A94B; border-radius: 12px; color: #43351C;
}
.cal-note p + p { margin-top: 10px; font-size: 0.975rem; line-height: 1.6; }
.cal-note-how {
  margin-top: 16px !important; padding: 10px 14px; background: #FFFFFF;
  border: 1px solid #E8D9B4; border-radius: 8px;
  font-family: var(--font-mono); font-size: 0.85rem;
}

/* One orchestrated moment on load. Nothing else on the page moves except the
   dial's markers, which move with the clock, and a slow breath on the cities
   that are in daytime. */
@media (prefers-reduced-motion: no-preference) {
  .chero .crumbs, .chero h1, .chero-lead, .chero-facts, .chero-alt {
    animation: chero-in .7s cubic-bezier(.2, .7, .2, 1) both;
  }
  .chero h1 { animation-delay: .06s; }
  .chero-lead { animation-delay: .18s; }
  .chero-facts { animation-delay: .28s; }
  .chero-alt { animation-delay: .38s; }
  .dial-face, .dial-base, .dial-ticks, .dial-hours, .dial-centre, .dial-wrap::before { animation: chero-in .8s cubic-bezier(.2, .7, .2, 1) .2s both; }
  .dial-day { stroke-dasharray: 0 24; animation: dial-day 1.2s cubic-bezier(.3, .6, .2, 1) .5s forwards; }
  .dial-mark { animation: dial-mark .6s cubic-bezier(.2, .7, .2, 1) both; }
  .dial-mark:nth-child(1) { animation-delay: 1.2s; }
  .dial-mark:nth-child(2) { animation-delay: 1.28s; }
  .dial-mark:nth-child(3) { animation-delay: 1.36s; }
  .dial-mark:nth-child(4) { animation-delay: 1.44s; }
  .dial-mark:nth-child(5) { animation-delay: 1.52s; }
  .dial-mark:nth-child(6) { animation-delay: 1.6s; }
  .dial-mark:nth-child(7) { animation-delay: 1.72s; }
  .dial-key { animation: chero-in .6s ease 1.9s both; }
  .dial-glow { transform-box: fill-box; transform-origin: center; animation: dial-glow 3.2s ease-in-out infinite; }
  .chero-card { animation: chero-card-in .9s cubic-bezier(.2, .7, .2, 1) .5s both; }
}
@keyframes chero-in { from { opacity: 0; transform: translateY(12px); } }
@keyframes chero-card-in { from { opacity: 0; transform: translateY(30px) scale(.985); } }
@keyframes dial-day { to { stroke-dasharray: 13 11; } }
@keyframes dial-mark { from { opacity: 0; } }
@keyframes dial-glow { 0%, 100% { transform: scale(1); opacity: .9; } 50% { transform: scale(2.6); opacity: 0; } }

/* The three direct channels as three deep tiles on the mist ground, each in
   its own colour: navy for the written channel, green for the one most of
   the Gulf clients use, amber for the one you pick up when something is on
   fire. White type, a light accent of the same hue for the glyph, the
   underline and the small labels, so each tile is one colour family. */
.reach-row { list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 2vw, 24px); }
.reach {
  --tile: var(--ink); --tile-accent: #8CC7F7; --tile-soft: rgba(255, 255, 255, 0.78);
  position: relative; padding: clamp(24px, 2.6vw, 32px); border-radius: 18px;
  background: var(--tile); color: var(--white);
  box-shadow: 0 18px 40px rgba(15, 42, 74, 0.14);
}
.reach--whatsapp { --tile: #0B5E30; --tile-accent: #8EE5B2; }
.reach--phone { --tile: #8A4708; --tile-accent: #FFCB7A; }
.reach-kind {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-head); font-weight: 600; font-size: 0.95rem; color: var(--tile-accent);
}
.reach-glyph { width: 22px; height: 22px; fill: none; stroke: var(--tile-accent); stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.reach-at {
  margin-top: 16px; font-family: var(--font-head); font-weight: 600; line-height: 1.25;
  font-size: clamp(1.15rem, 1rem + 0.6vw, 1.45rem);
}
.reach-at a {
  color: var(--white); text-decoration: none; overflow-wrap: anywhere;
  border-bottom: 3px solid var(--tile-accent); transition: color .15s ease;
}
.reach-at a:hover { color: var(--tile-accent); }
/* Two numbers in one tile: a little tighter, each with where it rings. */
.reach-at--multi { font-size: clamp(1.05rem, 0.95rem + 0.45vw, 1.3rem); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.reach-at--multi + .reach-at--multi { margin-top: 10px; }
.reach-where { font-family: var(--font-body); font-weight: 400; font-size: 0.85rem; color: var(--tile-accent); }
.reach-when { margin-top: 18px; font-size: 0.95rem; line-height: 1.6; color: var(--tile-soft); max-width: 34ch; }
.reach-foot {
  margin-top: clamp(36px, 4vw, 52px); padding-top: 28px; border-top: 1px solid #D3DEEA;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 28px 48px; align-items: start;
}
.reach-office { font-size: 0.975rem; line-height: 1.65; color: #44546A; max-width: 44ch; }
.reach-office strong { color: var(--ink); font-weight: 600; }
/* The three facts about reaching us, with the firm's tick. */
.reach-facts { list-style: none; display: grid; gap: 18px; }
.reach-facts li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 12px; align-items: start; }
.reach-facts .tk { grid-row: auto; margin-top: 2px; stroke: #1C8A57; }
.reach-facts .tk .tk-disc { fill: rgba(28, 138, 87, 0.1); stroke: rgba(28, 138, 87, 0.35); }
.reach-facts h3 { font-family: var(--font-head); font-weight: 600; font-size: 0.975rem; color: var(--ink); }
.reach-facts p { margin-top: 4px; font-size: 0.925rem; line-height: 1.6; color: #44546A; max-width: 46ch; }

@media (max-width: 1000px) {
  .chero-grid { grid-template-columns: minmax(0, 1fr); gap: 40px; margin-top: 24px; }
  .chero h1 { max-width: 16ch; }
  .dial-wrap { max-width: 640px; margin-inline: auto; }
  .reach-foot { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 700px) {
  .chero { --cal-overlap: 80px; }
  .chero + .section { padding-top: calc(80px + 40px); }
  .dial-label { font-size: 22px; }
  .reach-row { grid-template-columns: minmax(0, 1fr); }
  .reach { padding: 18px 0; }
  .reach:first-child { padding-top: 0; }
  .reach-path { margin-top: 14px; max-width: 280px; }
  .reach + .reach { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 560px) {
  [id$="my-cal-inline-odoo-consultation"] { min-height: 560px; }
  .chero-card { padding: 10px 10px 8px; border-radius: 14px; }
  .chero-card-title { padding: 4px 4px 10px; }
}

/* ---- migration ----
   The hero object: pick the version you run and the edition you are on, and
   read what that means right now. A white card on the navy, like the
   calendar. The chips run red at 10 to green at 20, each tinted at rest and
   filled when chosen, so the scale is read before anyone clicks and the
   status is a colour and a word, never the colour alone. */
.vpick {
  background: var(--white); color: var(--graphite); border-radius: 18px;
  padding: clamp(20px, 2.4vw, 28px);
  box-shadow: 0 32px 90px rgba(2, 12, 28, 0.35), 0 1px 0 rgba(255, 255, 255, 0.35) inset;
}
.vpick-q { font-family: var(--font-head); font-weight: 600; font-size: 1.05rem; color: var(--ink); }
.vpick-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.vchip {
  --chip: var(--graphite);
  min-width: 42px; height: 40px; padding: 0 10px; border-radius: 10px; cursor: pointer;
  font-family: var(--font-head); font-weight: 600; font-size: 0.95rem; font-variant-numeric: tabular-nums;
  color: var(--chip); background: color-mix(in srgb, var(--chip) 10%, white);
  border: 1.5px solid color-mix(in srgb, var(--chip) 35%, white);
  transition: background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.vchip:hover { background: color-mix(in srgb, var(--chip) 18%, white); border-color: var(--chip); }
.vchip[aria-pressed="true"] { background: var(--chip); color: var(--white); border-color: var(--chip); box-shadow: 0 0 0 4px color-mix(in srgb, var(--chip) 25%, white); }
.vchip:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.vpick-ed { display: inline-flex; margin-top: 16px; padding: 3px; border-radius: 999px; background: var(--mist); border: 1px solid #DFE8F3; }
.vpill {
  padding: 7px 14px; border-radius: 999px; border: 0; cursor: pointer;
  font-family: var(--font-head); font-weight: 600; font-size: 0.85rem; color: var(--graphite); background: transparent;
}
.vpill.is-on { background: var(--ink); color: var(--white); }
.vpick-out { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line); }
.vpick-status { display: flex; align-items: center; gap: 10px; font-family: var(--font-head); font-weight: 600; font-size: 1rem; color: var(--ink); }
.vpick-dot { width: 10px; height: 10px; border-radius: 50%; background: #9FB0C4; flex: none; }
.vpick-out.is-current .vpick-dot, .vpick-out.is-supported .vpick-dot { background: #118811; box-shadow: 0 0 0 4px rgba(17, 136, 17, 0.16); }
.vpick-out.is-ending .vpick-dot { background: #966A13; box-shadow: 0 0 0 4px rgba(150, 106, 19, 0.18); }
.vpick-out.is-ended .vpick-dot { background: #B61616; box-shadow: 0 0 0 4px rgba(182, 22, 22, 0.14); }
.vpick-text { margin-top: 10px; font-size: 0.95rem; line-height: 1.6; color: var(--ink); }
.vpick-path { margin-top: 10px; font-size: 0.925rem; line-height: 1.6; color: var(--graphite); }
.vpick-foot { margin-top: 16px; font-size: 0.78rem; line-height: 1.5; color: #7A8898; }
@media (prefers-reduced-motion: no-preference) {
  .vpick-out.is-fresh .vpick-status, .vpick-out.is-fresh .vpick-text, .vpick-out.is-fresh .vpick-path { animation: chero-in .35s ease both; }
  .vpick-out.is-fresh .vpick-text { animation-delay: .05s; }
  .vpick-out.is-fresh .vpick-path { animation-delay: .1s; }
}

/* ---- support ----
   The hero object: say what is happening and read what kind of help it is,
   who picks it up and what to send. Same white card as the version picker,
   chips as whole phrases because the choices are situations, not numbers. */
.tri {
  background: var(--white); color: var(--graphite); border-radius: 18px;
  padding: clamp(20px, 2.4vw, 28px);
  box-shadow: 0 32px 90px rgba(2, 12, 28, 0.35), 0 1px 0 rgba(255, 255, 255, 0.35) inset;
}
.tri-q { font-family: var(--font-head); font-weight: 600; font-size: 1.05rem; color: var(--ink); }
.tri-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.tchip {
  padding: 9px 13px; border-radius: 999px; cursor: pointer; text-align: left;
  font-family: var(--font-head); font-weight: 500; font-size: 0.875rem; line-height: 1.2;
  color: var(--ink); background: var(--mist); border: 1.5px solid #DFE8F3;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.tchip:hover { border-color: var(--action); background: #E3F0FC; }
.tchip[aria-pressed="true"] { background: var(--action); color: var(--white); border-color: var(--action); }
.tchip:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.tri-out { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line); }
.tri-kind { display: flex; align-items: center; gap: 10px; font-family: var(--font-head); font-weight: 600; font-size: 1rem; color: var(--ink); }
.tri-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--action); box-shadow: 0 0 0 4px rgba(21, 101, 192, 0.14); flex: none; }
.tri-panel--intro .tri-dot { background: #9FB0C4; box-shadow: none; }
.tri-intro { margin-top: 10px; font-size: 0.95rem; line-height: 1.6; color: var(--ink); }
.tri-facts { margin-top: 12px; display: grid; gap: 10px; }
.tri-facts dt { font-size: 0.78rem; letter-spacing: 0.01em; color: var(--graphite); }
.tri-facts dd { margin-top: 2px; font-size: 0.925rem; line-height: 1.55; color: var(--ink); }
@media (prefers-reduced-motion: no-preference) {
  .tri-panel.is-fresh { animation: chero-in .3s ease both; }
}

/* The version table. Status as a tinted word, the row itself untinted so the
   dates stay readable. */
.vtable-wrap { margin-top: 24px; overflow-x: auto; }
.vtable { width: 100%; border-collapse: collapse; font-size: 0.95rem; min-width: 560px; }
.vtable th, .vtable td { text-align: left; padding: 12px 14px 12px 0; border-top: 1px solid var(--line); vertical-align: top; }
.vtable thead th { font-family: var(--font-head); font-weight: 600; font-size: 0.85rem; color: var(--graphite); border-top: 0; padding-top: 0; }
.vtable tbody th { font-family: var(--font-head); font-weight: 600; color: var(--ink); white-space: nowrap; }
.vtable td { color: var(--graphite); }
.vstat { display: inline-block; padding: 3px 10px; border-radius: 999px; font-family: var(--font-head); font-weight: 600; font-size: 0.8rem; white-space: nowrap; }
.vstat--current { background: #E3F0FC; color: #0F4F9C; }
.vstat--supported { background: #E6F4EC; color: #1C6E45; }
.vstat--ending { background: #FBECD6; color: #8A4708; }
.vstat--ended { background: #EEF1F5; color: #565757; }

.mode-you { margin-top: 10px !important; font-size: 0.925rem; color: var(--graphite); }
.mode-you strong { color: var(--ink); font-weight: 600; }
.scope--method > div { border-top-color: #D3DEEA; }

@media (max-width: 1000px) {
  .vpick { margin-top: 8px; }
}

/* ---- the integration logo wall ----
   Mono marks that paint themselves with currentColor, so the colour of a mark
   is just the colour of its text. That is the whole reason these are inlined
   rather than served as images: an <img> is its own document and cannot see
   the colour around it, so every mark would come out black and nothing here
   would work.

   It also means the wall needs no second set of rules to sit on a dark panel.
   Change the colour on .ilogo-mark and every mark follows. */
/* The category label sits beside its row, not above it. Six stacked grids read
   as a long list and each one's ragged right edge looks unfinished. Six bands
   with the labels in a column read as one table, and the ragged edge becomes
   the natural end of a band.

   It also removes the stranded card. With a label column taking its width, no
   category's count lands exactly one short of a full row, which is what left
   Zoom sitting alone under seven others. */
.ilogos { display: grid; margin-top: 24px; }
.ilogo-cat {
  display: grid; grid-template-columns: 148px minmax(0, 1fr); gap: 24px;
  align-items: start; padding: 22px 0; border-top: 1px solid var(--line);
}
.ilogo-cat:first-child { border-top: 0; padding-top: 4px; }
.ilogo-cat h3 {
  margin: 0; padding-top: 12px;
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--graphite);
}
.ilogo-grid {
  list-style: none; display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
}
/* Narrow enough and the label has no room beside the row, so it goes back on
   top of it. */
@media (max-width: 760px) {
  .ilogo-cat { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 18px 0; }
  .ilogo-cat h3 { padding-top: 0; }
}
.ilogo {
  display: grid; justify-items: center; align-content: start; gap: 10px;
  padding: 18px 8px; border: 1px solid var(--line); border-radius: 12px;
  background: #FFFFFF;
}
.ilogo-mark { position: relative; width: 40px; height: 40px; color: #78889C; }
.ilogo-mark svg { width: 100%; height: 100%; display: block; }
/* A mark that carries more than one colour ships twice. The brand version
   sits exactly on top of the mono one and is revealed on hover, which is the
   only way to show such a mark in its real colours without altering it. */
.ilogo-full { position: absolute; inset: 0; opacity: 0; }
.ilogo-name {
  font-size: 0.75rem; line-height: 1.3; text-align: center; color: var(--graphite);
  /* never inside a word: "WooCommerc / e" is worse than a second line */
  overflow-wrap: normal; hyphens: none;
}
.ilogo-foot { margin-top: 22px; font-size: 0.82rem; color: var(--graphite); }

/* Brand colour on hover, and only where hovering is a thing. On a touch
   screen there is no hover state to reach, so the marks simply stay grey
   rather than sitting in a state nobody asked for. */
@media (any-hover: hover) {
  .ilogo { transition: border-color .18s ease, background-color .18s ease; }
  .ilogo-mark { transition: color .18s ease; }
  .ilogo:hover { border-color: color-mix(in srgb, var(--brand) 45%, var(--line)); }
  .ilogo:hover .ilogo-mark { color: var(--brand); }
  .ilogo-full { transition: opacity .18s ease; }
  .ilogo--two:hover .ilogo-full { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .ilogo, .ilogo-mark { transition: none; }
}

/* ---- the wall on the dark panel ----
   White cards on a white page are defined by a hairline and nothing else,
   which is why the wall read as flat. On the dark panel the marks become the
   lit thing in the section rather than grey texture on grey.

   It also fixes a contrast problem rather than trading one for another. Five
   of these brands have official colours too pale to read on white: DHL's
   yellow managed 1.51:1 there. Against this panel those are the brightest
   marks on the page, and the dark brands that were strongest on white still
   hold because the card sits lighter than the panel behind it. */
.panel--dark .ilogo-cat { border-top-color: rgba(255, 255, 255, 0.1); }
.panel--dark .ilogo-cat h3 { color: #8FA8C4; }
.panel--dark .ilogo {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.11);
}
.panel--dark .ilogo-mark { color: #9FB6CF; }
.panel--dark .ilogo-name { color: #C9D6E6; }
.panel--dark .ilogo-foot { color: #8FA8C4; }
@media (any-hover: hover) {
  .panel--dark .ilogo:hover {
    background: rgba(255, 255, 255, 0.09);
    border-color: color-mix(in srgb, var(--brand) 55%, rgba(255, 255, 255, 0.11));
  }
}

/* The homepage row. One line of marks, no category headings, and a way
   through to the page that explains them. */
.ilogo-band-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 20px; flex-wrap: wrap; margin-bottom: clamp(22px, 2.6vw, 30px);
}
.ilogo-band-head h2 { font-size: clamp(1.35rem, 2.2vw, 1.7rem); }
.ilogo-band-head a { font-weight: 500; white-space: nowrap; }
.ilogo-grid--row { grid-template-columns: repeat(11, minmax(0, 1fr)); gap: 8px; }
.ilogo-grid--row .ilogo { padding: 14px 6px; gap: 8px; }
.ilogo-grid--row .ilogo-mark { width: 30px; height: 30px; }
.ilogo-grid--row .ilogo-name { font-size: 0.72rem; }

/* Eleven across stops being a row long before phone width. It steps down
   rather than scrolling sideways, because a strip that scrolls is a strip
   half of which is never seen. */
@media (max-width: 1100px) { .ilogo-grid--row { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .ilogo-grid--row { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 420px)  {
  .ilogo-grid--row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ilogo-grid { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); }
  .ilogo { padding: 14px 6px; }
}

/* The licensing note. Not a warning box: it is the most useful thing on the
   page for someone who has not bought yet, so it reads as advice. */
.plans-note {
  margin-top: clamp(26px, 3vw, 34px); padding: clamp(20px, 2.4vw, 26px);
  background: #F4F8FC; border: 1px solid #DCE6F0; border-radius: 14px;
}
.plans-note h3 { font-size: 0.95rem; }
.plans-note p { margin-top: 8px; font-size: 0.975rem; line-height: 1.65; max-width: 72ch; }

.sec-lead { margin-top: 14px; font-size: 1.0625rem; line-height: 1.65; max-width: 66ch; }
.panel--dark .sec-lead { color: #B6C9DD; }

/* Two cards rather than three: they take half the row each instead of leaving
   a hole where the third would be. */
.proof--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 560px) { .proof--two { grid-template-columns: 1fr; } }

/* ---- the Customization hero: an Odoo 18 sales order, changed ---- */
/* Built against a real screen, not from memory. The parts that make an Odoo
   user recognise it instantly are the control panel with the New button and
   the breadcrumb, the plum primary action, the chevron statusbar sitting to
   the right of the buttons, the record number set large, fields as label
   beside value, and the notebook tabs. Teal is Odoo's link colour, plum its
   primary. The standard fields are there from the start; only the three
   changes arrive, each tinted by whether it was made in Studio or in code. */
.formview {
  margin: 0; border-radius: 14px; overflow: hidden; background: #FFFFFF;
  border: 1px solid rgba(255, 255, 255, 0.28);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.55);
}
.fv-top {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px; background: #F9F9FA; border-bottom: 1px solid #E5E5EA;
}
.fv-new {
  flex: none; padding: 4px 11px; border-radius: 5px;
  border: 1px solid #C9C9D3; background: #FFFFFF;
  font-family: var(--font-head); font-weight: 500; font-size: 0.72rem; color: #3C3C46;
}
.fv-crumb { display: grid; line-height: 1.25; min-width: 0; }
.fv-crumb-up { font-size: 0.68rem; color: #017E84; }
.fv-rec { font-family: var(--font-head); font-weight: 600; font-size: 0.8rem; color: #1F1F28; }
.fv-pager { margin-left: auto; flex: none; font-size: 0.68rem; color: #70707E; }

.fv-head {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  padding: 11px 14px; border-bottom: 1px solid #EDEDF1;
}
.fv-btn {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  padding: 5px 11px; border-radius: 5px; border: 1px solid #C9C9D3;
  background: #FFFFFF; color: #3C3C46;
  font-family: var(--font-head); font-weight: 500; font-size: 0.74rem;
}
.fv-btn--go { background: #714B67; border-color: #714B67; color: #FFFFFF; }
.fv-btn--new.fv-btn--code { border-color: #7FA882; color: #2C5B2E; background: #F0F6EE; }
.fv-btn .fv-tag { padding: 1px 6px; font-size: 0.56rem; }

/* Odoo's statusbar: joined chevrons, not separate pills. */
.fv-stages { list-style: none; display: flex; margin-left: auto; flex: none; }
.fv-stage {
  padding: 5px 13px 5px 17px; margin-left: -8px;
  background: #FFFFFF; border: 1px solid #D7D7DF; border-left: 0;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%, 8px 50%);
  font-family: var(--font-head); font-weight: 500; font-size: 0.68rem; color: #6A6A78;
  white-space: nowrap;
}
.fv-stage:first-child {
  margin-left: 0; padding-left: 13px; border-left: 1px solid #D7D7DF;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%);
}
.fv-stage.is-on { background: #E4EFEF; color: #17585C; }

.fv-sheet { padding: 16px 16px 0; }
.fv-title {
  font-family: var(--font-head); font-weight: 700; font-size: 1.65rem;
  color: #11111A; line-height: 1.05; letter-spacing: -0.01em;
}
.fv-fields { margin-top: 14px; display: grid; gap: 1px; }
.fv-f {
  display: grid; grid-template-columns: 124px minmax(0, 1fr) auto;
  align-items: baseline; gap: 10px; padding: 6px 8px; border-radius: 5px;
}
.fv-l { font-size: 0.74rem; color: #686876; }
.fv-v { font-size: 0.78rem; font-weight: 500; color: #1F1F28; min-width: 0; }
.fv-v--link { color: #017E84; font-weight: 600; }
/* The tint names which kind of change it is, and the tag spells it out.
   A Code change wearing Studio's colour would be the one thing this graphic
   must not do, since telling them apart is the whole point of the page. */
.fv-f--studio { background: #F7F1F5; box-shadow: inset 2px 0 0 #9E7B93; }
.fv-f--code { background: #F0F6EE; box-shadow: inset 2px 0 0 #6FA173; }
.fv-tag {
  flex: none; padding: 2px 8px; border-radius: 999px;
  font-family: var(--font-head); font-weight: 600; font-size: 0.62rem; letter-spacing: 0.02em;
}
.fv-tag--studio { background: #EADFE7; color: #5E3C55; }
.fv-tag--code { background: #D9EAD3; color: #2C5B2E; }

.fv-tabs {
  list-style: none; display: flex; gap: 2px; margin-top: 16px;
  border-bottom: 1px solid #E5E5EA;
}
.fv-tab {
  padding: 8px 13px; border-bottom: 2px solid transparent;
  font-family: var(--font-head); font-weight: 500; font-size: 0.74rem; color: #6A6A78;
  white-space: nowrap;
}
.fv-tab.is-on { color: #714B67; border-bottom-color: #714B67; }

.fv-done {
  margin: 13px 16px 14px; padding-top: 11px; border-top: 1px solid #EDEDF1;
  font-size: 0.76rem; color: #5A5A68;
}

@media (prefers-reduced-motion: no-preference) {
  /* :not(.is-in) matters. The animation fills backwards, so once it has
     finished the field falls back to its own styles, and without this guard
     that means opacity 0 and the change disappears again. */
  .formview.is-armed:not(.is-in) .fv-f--new,
  .formview.is-armed:not(.is-in) .fv-btn--new { opacity: 0; }
  .formview.is-armed.is-in .fv-f--new,
  .formview.is-armed.is-in .fv-btn--new {
    animation: fv-land .46s cubic-bezier(.34, 1.4, .52, 1) backwards;
    animation-delay: calc(560ms + var(--i) * 640ms);
  }
}
@keyframes fv-land {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: none; }
}

@media (max-width: 560px) {
  .fv-stages { display: none; }
  .fv-title { font-size: 1.4rem; }
  .fv-f { grid-template-columns: minmax(0, 1fr) auto; gap: 1px 8px; }
  .fv-l { grid-column: 1; }
  .fv-v { grid-column: 1; }
  .fv-tag { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
  .fv-tabs .fv-tab:last-child { display: none; }
}

/* ---- the comparison: the dark anchor of the Customization page ---- */
/* It sits on the dark panel because it is the most important thing on the
   page and it was previously the lightest, which left the page with no
   centre of gravity. A table, not two cards: the point of a comparison is
   reading across a row, and separate boxes make that the one thing you
   cannot do. Each column keeps its own colour so the eye can also track
   down, and the last row is lit because "the catch" is the row that earns
   the page its credibility. */
.panel--dark .doc-lead, .panel--dark > h2 + p { color: #A9C0D8; max-width: 72ch; }

.vs {
  width: 100%; border-collapse: separate; border-spacing: 0;
  margin-top: clamp(28px, 3.2vw, 38px);
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.13); border-radius: 16px;
  overflow: hidden; text-align: left;
}
.vs-cap { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

.vs-corner { width: 150px; }
.vs-head {
  width: 38%; vertical-align: top;
  padding: clamp(20px, 2.2vw, 26px) clamp(16px, 1.8vw, 22px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.13);
  border-top: 3px solid var(--vs);
  background: linear-gradient(180deg, var(--vs-wash), transparent);
}
.vs-head--studio { --vs: #B57FC8; --vs-wash: rgba(181, 127, 200, 0.14); }
.vs-head--module { --vs: #5BA8EE; --vs-wash: rgba(91, 168, 238, 0.14); }
.vs-head .mk {
  width: 26px; height: 26px; padding: 0; background: none; border-radius: 0;
  color: var(--vs); margin-bottom: 9px; stroke-width: 1.7;
}
.vs-head .mk .mk-fill { fill: none; }
.vs-name {
  display: block; font-family: var(--font-head); font-weight: 600;
  font-size: 1.15rem; color: var(--white);
}
.vs-sub {
  display: block; margin-top: 5px; font-size: 0.85rem; line-height: 1.5;
  color: #9FB6CF; font-weight: 400;
}

.vs-row th[scope="row"] {
  width: 150px; vertical-align: top; padding: 17px clamp(14px, 1.6vw, 20px);
  border-right: 1px solid rgba(255, 255, 255, 0.1);
  font-family: var(--font-head); font-weight: 600; font-size: 0.8rem; color: #9FB6CF;
}
.vs-row td {
  vertical-align: top; padding: 17px clamp(16px, 1.8vw, 22px);
  font-size: 0.9rem; line-height: 1.6; color: #B6C9DD;
}
.vs-row td + td { border-left: 1px solid rgba(255, 255, 255, 0.1); }
.vs-row + .vs-row th, .vs-row + .vs-row td { border-top: 1px solid rgba(255, 255, 255, 0.1); }
/* The honest row, lit rather than hidden. */
.vs-row--catch th[scope="row"], .vs-row--catch td { background: rgba(232, 192, 122, 0.07); }
.vs-row--catch th[scope="row"] { color: #E8C07A; }

/* Below this a three-column table stops being readable, so it reflows: the
   row label, then each option's answer under its own name. Still a
   comparison, just read down instead of across. */
@media (max-width: 860px) {
  .vs, .vs tbody, .vs tr, .vs th, .vs td { display: block; width: auto; }
  .vs thead { display: none; }
  .vs-row { border-top: 1px solid rgba(255, 255, 255, 0.1); }
  .vs tbody .vs-row:first-child { border-top: 0; }
  .vs-row th[scope="row"] {
    width: auto; border-right: 0; padding: 15px 18px 10px;
    font-size: 0.9rem; color: var(--white);
  }
  .vs-row td { padding: 0 18px 15px; border-left: 0 !important; border-top: 0 !important; }
  .vs-row td::before {
    content: attr(data-col); display: block; margin-bottom: 3px;
    font-family: var(--font-head); font-weight: 600; font-size: 0.72rem; color: var(--vs, #9FB6CF);
  }
  .vs-row td:nth-of-type(1) { --vs: #B57FC8; }
  .vs-row td:nth-of-type(2) { --vs: #5BA8EE; }
  .vs-row--catch th[scope="row"] { color: #E8C07A; }
}


/* ---- "Who writes it", over the office ---- */
/* The footage is blurred in the file itself, not in CSS. A CSS blur still
   ships the sharp original to every browser, and blurring video live is
   expensive on a mid-range phone.

   The veil over it is pale, not dark. The section after this one is the dark
   panel, and two dark bands in a row give the page no rhythm. So the office
   sits behind a near-white wash and the type stays the same ink as every
   other light section.

   The wash is deliberately uneven. It only has to be strong where the words
   are, so it holds near-opaque across the text column and then drops away
   hard, leaving the footage plainly visible over the right-hand side where
   there is nothing to read. A veil strong enough everywhere is just fog.
   The stops were tuned against the real moving pixels, not by eye. */
.panel--film {
  position: relative; overflow: hidden; isolation: isolate;
  background: #F5F7FA; border: 1px solid #E3E8EE;
}
.film {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 42%;
  z-index: 0; pointer-events: none;
}
.film-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* Strong over the words on the left, then away quickly: the sign on the
     wall sits from about 37% across, and that is what has to stay visible. */
  background:
    linear-gradient(97deg, rgba(247, 249, 251, 0.93) 0%, rgba(247, 249, 251, 0.89) 44%,
                    rgba(246, 249, 252, 0.72) 51%, rgba(246, 249, 252, 0.3) 62%,
                    rgba(245, 249, 252, 0.12) 78%, rgba(245, 249, 252, 0.07) 100%);
}
.film-in { position: relative; z-index: 2; }

/* The photographs need a touch more edge than they do on a flat background,
   since they now sit on something with texture in it. */
/* The counter sits at 47 to 51 percent, right where the veil falls away, so
   it needs to carry itself rather than lean on the wash. */
.panel--film .shots-count { color: #1B2533; }
.panel--film .shot img { border-color: rgba(15, 42, 74, 0.14); box-shadow: 0 12px 28px -18px rgba(15, 42, 74, 0.5); }

/* Nobody who asked for less motion gets a moving background, and nobody on a
   metered connection pays for one either. The poster carries the section. */
@media (prefers-reduced-motion: reduce) { .film { display: none; } }
