/* ==========================================================================
   OLD PORT UAE  ·  oldport.ae  ·  core tokens + motion system
   The ONLY site-wide stylesheet. Everything else is scoped to .opuae-*
   Install: Elementor > Site Settings > Custom CSS  (or Customize > Additional CSS)
   The op-uae-core plugin also enqueues this file automatically.
   ========================================================================== */

:root{
  /* --- palette: red / black / white --- */
  --opuae-red:#E10600;
  --opuae-red-deep:#A80400;
  /* #E10600 on black is 4.23:1, which fails WCAG AA for small text.
     This brighter red is 5.60:1 on black and is used for red TEXT inside
     dark sections. Fills, rules and large display type keep the brand red. */
  --opuae-red-text:#E10600;
  --opuae-red-on-dark:#FF2A20;
  --opuae-red-glow:rgba(225,6,0,.16);
  --opuae-black:#000000;
  --opuae-ink:#0A0A0A;
  --opuae-white:#FFFFFF;
  --opuae-paper:#F4F4F5;
  --opuae-line:#DCDCDE;
  --opuae-line-dark:#232326;
  --opuae-mute:#6B6B70;
  --opuae-mute-dark:#A9A9B0;

  /* --- type --- */
  --opuae-display:"Barlow Condensed","Oswald",Impact,sans-serif;
  --opuae-body:"Inter","Helvetica Neue",Arial,sans-serif;
  --opuae-mono:"Share Tech Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* --- layout --- */
  --opuae-max:1280px;
  --opuae-gutter:clamp(18px,4.2vw,56px);
  --opuae-radius:0px;

  /* Vertical rhythm between sections.

     This was the same clamp() hardcoded in ten block files. Tuning it meant
     ten edits that had to agree, and the old value (max 124px) put 248px of
     dead air between every section: on a 1707x842 screen that is more than a
     quarter of the viewport of nothing, which read as a rendering fault
     rather than as space. Scale it against the viewport HEIGHT the reader
     actually has, not its width.

     Blocks use var(--opuae-sec-y). tools/qa.py fails any block that
     hardcodes a section clamp instead. */
  --opuae-sec-y:clamp(52px,5.4vw,90px);
  /* Thin bands: the client strip, and anything else that is a rule rather
     than a chapter. */
  --opuae-sec-y-sm:clamp(38px,4vw,64px);

  /* ----------------------------------------------------------------------
   Theme isolation.

   These blocks drop into whatever theme the site runs, and a theme styles
   bare elements. Anything we leave unset is the theme's to colour: with no
   ::selection rule of our own, the theme's accent painted the highlight
   (a pink #CC3366 band on an accordion header or a close button looked like
   our own hover state, and was not), and a theme's button or link rules
   reach our controls wherever we only set colour.

   So: state our own selection colour, and reset the bare elements we build
   controls from. Cheap, and it makes the blocks behave the same under any
   theme.
   -------------------------------------------------------------------- */
.opuae-site ::selection{background:var(--opuae-red);color:var(--opuae-white)}
.opuae-site ::-moz-selection{background:var(--opuae-red);color:var(--opuae-white)}

/* Theme isolation. Two different jobs, so two rules. Collapsing them into
   one is what made this oscillate between two bugs.

   STRIP applies to every button on the page, ours included. The theme paints
   a pink (#CC3366) hover fill from a rule our single-class selectors cannot
   out-specify, so clearing the background here is the only thing keeping it
   off our accordion headers and close buttons. Narrowing this to non-opuae
   buttons let the pink straight back in.

   OURS carries only the properties that belong to the component, not to the
   reset. Applying colour and margin to our own buttons from here is what
   turned the submit button's text to the page ink on a dark hover fill, and
   flattened the menu button's alignment.

   Our own buttons re-declare their background below under .opuae-site, at
   (0,2,0), so they out-specify STRIP without weakening it. */
.opuae-site button:not([class*="opuae-"]){background-color:transparent;border:0;margin:0;font:inherit;color:inherit;
  -webkit-tap-highlight-color:transparent}
.opuae-site button:not([class*="opuae-"]):hover,
.opuae-site button:not([class*="opuae-"]):focus{background-color:transparent}
.opuae-site a{-webkit-tap-highlight-color:transparent}

/* white-space is INHERITED, which is what made this one hard to see.
   hello-elementor's reset.css carries:

     [type="button"],[type="submit"],button{white-space:nowrap}

   Our accordion header is a <button>, so every question inside it inherited
   nowrap and laid out on one line. "Where are you based, and do you work
   outside the UAE?" came to 437px inside a 390px phone, which stretched the
   page to 497px: the sticky CTA bar, the cookie notice, the WhatsApp button
   and the chat launcher then all resolved against that wider box and sat
   partly off screen. One inherited property, five things visibly broken, and
   the site-level overflow-x:hidden hid the horizontal scrollbar that would
   have given it away.

   It is declared here rather than per component because the theme's rule is
   element-level and applies to every button we ship: the service tabs were
   bleeding too. normal is the browser's own default, so this restores
   expected behaviour rather than imposing anything. A control that genuinely
   wants one line declares nowrap for itself, which is the right way round.

   tools/qa.py asserts the page is not wider than the viewport with the
   clamp lifted, which is the check that would have caught it. */
.opuae-site button,.opuae-site [type="button"],.opuae-site [type="submit"]{white-space:normal}

.opuae-site input,.opuae-site textarea,.opuae-site select{font:inherit;accent-color:var(--opuae-red)}
/* A visible, branded focus ring, so keyboard focus never falls back to the
   theme's or the browser's. */
.opuae-site :focus-visible{outline:2px solid var(--opuae-red);outline-offset:2px}

  /* --- MOTION SYSTEM --------------------------------------------------
     One easing vocabulary used by every block, so the whole site moves
     the same way. Never add a bespoke cubic-bezier inside a block.      */
  --opuae-ease:cubic-bezier(.22,.61,.36,1);      /* standard, out */
  --opuae-ease-soft:cubic-bezier(.4,0,.2,1);     /* in-out, for size */
  --opuae-ease-spring:cubic-bezier(.34,1.3,.64,1);/* slight overshoot */
  --opuae-t-fast:160ms;
  --opuae-t:280ms;
  --opuae-t-slow:520ms;
  --opuae-t-reveal:760ms;
}

/* Dark sections raise the red used for small text to keep contrast at AA. */
/* Every dark section. The brand red is 4.03:1 on this background and fails
   AA for small text, so on dark it becomes --opuae-red-on-dark. A new dark
   block that is not in this list ships an eyebrow at 4.23:1; the contrast
   check catches it, which is how .opuae-ph was added. */
.opuae-hero,.opuae-com,.opuae-pv,.opuae-ft,.opuae-cta,.opuae-abt,.opuae-ph,
.opuae-sv__hero,.opuae-sv__approach,.opuae-sv__cta,
.opuae-art__hero,.opuae-404,.opuae-acc--dark{--opuae-red-text:var(--opuae-red-on-dark)}

*,*::before,*::after{box-sizing:border-box}
html,body{max-width:100%;overflow-x:clip}
body{
  margin:0;
  font-family:var(--opuae-body);
  color:var(--opuae-ink);
  background:var(--opuae-white);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* Keyboard focus, inherited by every block */
[class*="opuae-"] :is(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--opuae-red);
  outline-offset:3px;
}

/* ==========================================================================
   SCROLL REVEAL
   JS adds .is-in when the element enters the viewport. A CSS-only fallback
   fires at 1.3s so content is NEVER permanently invisible if the JS fails.
   ========================================================================== */
.opuae-rv{
  opacity:0;
  transform:translateY(22px);
  transition:opacity var(--opuae-t-reveal) var(--opuae-ease),
             transform var(--opuae-t-reveal) var(--opuae-ease);
  transition-delay:var(--opuae-rv-d,0ms);
  will-change:opacity,transform;
  animation:opuae-failsafe 1ms linear 1.3s forwards;
}
.opuae-rv.is-in{opacity:1;transform:none;animation:none}
@keyframes opuae-failsafe{to{opacity:1;transform:none}}

/* stagger helpers */
.opuae-rv-1{--opuae-rv-d:70ms}
.opuae-rv-2{--opuae-rv-d:140ms}
.opuae-rv-3{--opuae-rv-d:210ms}
.opuae-rv-4{--opuae-rv-d:280ms}
.opuae-rv-5{--opuae-rv-d:350ms}
.opuae-rv-6{--opuae-rv-d:420ms}

/* Masked line reveal, used on big headlines */
.opuae-line-mask{display:block;overflow:hidden}
.opuae-line-mask > span{
  display:block;
  transform:translateY(102%);
  transition:transform var(--opuae-t-slow) var(--opuae-ease);
  transition-delay:var(--opuae-rv-d,0ms);
  animation:opuae-mask-failsafe 1ms linear 1.3s forwards;
}
.is-in > .opuae-line-mask > span,
.opuae-line-mask.is-in > span{transform:none;animation:none}
@keyframes opuae-mask-failsafe{to{transform:none}}

/* ==========================================================================
   SHARED ACCORDION  (.opuae-acc)
   Only ONE panel open at a time. Opens and closes smoothly in BOTH
   directions using the grid-template-rows 0fr -> 1fr technique, which
   animates to auto height without measuring in JS.
   Markup:
     <div class="opuae-acc" data-opuae-acc>
       <div class="opuae-acc__item">
         <button class="opuae-acc__head" aria-expanded="false" aria-controls="p1">
           <span class="opuae-acc__title">Question</span>
           <span class="opuae-acc__icon" aria-hidden="true"></span>
         </button>
         <div class="opuae-acc__panel" id="p1" role="region" hidden-until-found>
           <div class="opuae-acc__inner"><p>Answer</p></div>
         </div>
       </div>
     </div>
   ========================================================================== */
.opuae-acc__item{border-bottom:1px solid var(--opuae-line)}
.opuae-acc__item:first-child{border-top:1px solid var(--opuae-line)}

.opuae-acc__head{
  width:100%;
  display:flex;align-items:flex-start;justify-content:space-between;gap:20px;
  padding:clamp(18px,2.2vw,26px) 0;
  background:none;border:0;cursor:pointer;text-align:left;
  font-family:var(--opuae-body);
  font-size:clamp(16px,1.35vw,19px);
  font-weight:600;line-height:1.4;color:var(--opuae-ink);
  transition:color var(--opuae-t) var(--opuae-ease),
             padding-left var(--opuae-t) var(--opuae-ease);
}
.opuae-acc__head:hover{color:var(--opuae-red);padding-left:8px}
/* Declared, not inherited from a reset: this control sits on our own
   surface and must not pick up a theme's button fill. */
.opuae-site .opuae-acc__head,
.opuae-site .opuae-acc__head:hover,
.opuae-site .opuae-acc__head:focus{background:none}
.opuae-acc__head[aria-expanded="true"]{color:var(--opuae-red)}

/* plus -> minus, rotating smoothly */
.opuae-acc__icon{
  position:relative;flex:0 0 22px;width:22px;height:22px;margin-top:2px;
  transition:transform var(--opuae-t-slow) var(--opuae-ease-spring);
}
.opuae-acc__icon::before,
.opuae-acc__icon::after{
  content:"";position:absolute;left:50%;top:50%;
  background:currentColor;border-radius:2px;
  transform:translate(-50%,-50%);
  transition:opacity var(--opuae-t) var(--opuae-ease),
             transform var(--opuae-t-slow) var(--opuae-ease-spring);
}
.opuae-acc__icon::before{width:16px;height:2px}
.opuae-acc__icon::after{width:2px;height:16px}
.opuae-acc__head[aria-expanded="true"] .opuae-acc__icon{transform:rotate(180deg)}
.opuae-acc__head[aria-expanded="true"] .opuae-acc__icon::after{
  opacity:0;transform:translate(-50%,-50%) rotate(90deg) scaleX(.2);
}

/* the smooth part: height animates via fr, opacity trails it */
.opuae-acc__panel{
  display:grid;
  grid-template-rows:0fr;
  opacity:0;
  transition:grid-template-rows var(--opuae-t-slow) var(--opuae-ease-soft),
             opacity var(--opuae-t) var(--opuae-ease);
}
.opuae-acc__panel.is-open{
  grid-template-rows:1fr;
  opacity:1;
  transition:grid-template-rows var(--opuae-t-slow) var(--opuae-ease-soft),
             opacity var(--opuae-t) var(--opuae-ease) 90ms;
}
.opuae-acc__inner{
  overflow:hidden;
  min-height:0;             /* required for the fr collapse to work */
}
.opuae-acc__inner > *{margin:0 0 16px}
.opuae-acc__inner > *:first-child{padding-top:2px}
.opuae-acc__inner > *:last-child{margin-bottom:clamp(18px,2.2vw,26px)}
.opuae-acc__inner p{
  color:var(--opuae-mute);font-size:16px;line-height:1.65;max-width:68ch;
}
/* dark-section variant */
.opuae-acc--dark .opuae-acc__item{border-color:var(--opuae-line-dark)}
.opuae-acc--dark .opuae-acc__head{color:var(--opuae-white)}
.opuae-acc--dark .opuae-acc__inner p{color:var(--opuae-mute-dark)}

/* ==========================================================================
   SHARED BUTTONS
   ========================================================================== */
/* A container's generic "a" rule has higher specificity than .opuae-btn and
   would otherwise repaint buttons inside prose. These two rules make the
   button's own colours authoritative wherever it appears. */
a.opuae-btn.opuae-btn--red{color:var(--opuae-white);border-bottom:0}
a.opuae-btn.opuae-btn--dark{color:var(--opuae-white);border-bottom:0}
a.opuae-btn.opuae-btn--ghost{color:var(--opuae-ink);border-bottom-width:1px}
a.opuae-btn.opuae-btn--ghost-light{color:var(--opuae-white);border-bottom-width:1px}
a.opuae-btn.opuae-btn--ghost:hover{color:var(--opuae-white)}
a.opuae-btn.opuae-btn--ghost-light:hover{color:var(--opuae-black)}

.opuae-btn{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  gap:10px;padding:16px 28px;border:1px solid transparent;
  font-family:var(--opuae-body);font-size:15px;font-weight:600;letter-spacing:.01em;
  text-decoration:none;cursor:pointer;overflow:hidden;isolation:isolate;
  transition:color var(--opuae-t) var(--opuae-ease),
             border-color var(--opuae-t) var(--opuae-ease),
             transform var(--opuae-t) var(--opuae-ease);
}
.opuae-btn::before{
  content:"";position:absolute;inset:0;z-index:-1;
  transform:translateY(101%);
  transition:transform var(--opuae-t-slow) var(--opuae-ease);
}
.opuae-btn:hover{transform:translateY(-2px)}
.opuae-btn:active{transform:translateY(0)}
.opuae-btn:hover::before{transform:translateY(0)}

.opuae-site .opuae-btn--red{background:var(--opuae-red);color:var(--opuae-white)}
.opuae-btn--red::before{background:var(--opuae-black)}
.opuae-site .opuae-btn--dark{background:var(--opuae-black);color:var(--opuae-white)}
.opuae-btn--dark::before{background:var(--opuae-red)}
.opuae-site .opuae-btn--ghost{background:transparent;color:var(--opuae-ink);border-color:var(--opuae-ink)}
.opuae-btn--ghost::before{background:var(--opuae-ink)}
.opuae-site .opuae-btn--ghost:hover{color:var(--opuae-white)}
.opuae-site .opuae-btn--ghost-light{background:transparent;color:var(--opuae-white);border-color:rgba(255,255,255,.4)}
.opuae-btn--ghost-light::before{background:var(--opuae-white)}
.opuae-site .opuae-btn--ghost-light:hover{color:var(--opuae-black);border-color:var(--opuae-white)}

/* arrow that slides on hover */
.opuae-btn__arw{
  display:inline-block;width:16px;height:10px;position:relative;
  transition:transform var(--opuae-t) var(--opuae-ease);
}
.opuae-btn__arw::before{
  content:"";position:absolute;left:0;top:50%;width:100%;height:1.5px;
  background:currentColor;transform:translateY(-50%);
}
.opuae-btn__arw::after{
  content:"";position:absolute;right:0;top:50%;width:7px;height:7px;
  border-top:1.5px solid currentColor;border-right:1.5px solid currentColor;
  transform:translateY(-50%) rotate(45deg);
}
.opuae-btn:hover .opuae-btn__arw{transform:translateX(5px)}

/* ==========================================================================
   SHARED SECTION FURNITURE
   ========================================================================== */
.opuae-wrap{max-width:var(--opuae-max);margin:0 auto;padding-left:var(--opuae-gutter);padding-right:var(--opuae-gutter)}
.opuae-eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--opuae-mono);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--opuae-red-text);margin:0 0 18px;
}
.opuae-eyebrow::before{content:"";width:28px;height:2px;background:var(--opuae-red)}
.opuae-h2{
  font-family:var(--opuae-display);font-weight:700;
  font-size:clamp(32px,4.6vw,64px);line-height:1.02;letter-spacing:-.01em;
  margin:0 0 20px;text-transform:uppercase;
}
.opuae-lede{font-size:clamp(16px,1.3vw,19px);line-height:1.6;color:var(--opuae-mute);max-width:60ch;margin:0}

/* ==========================================================================
   REDUCED MOTION  ·  everything resolves to its end state instantly
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .opuae-rv{opacity:1;transform:none}
  .opuae-line-mask > span{transform:none}
}

/* ==========================================================================
   ARTICLE + ARCHIVE
   Used by the plugin's own templates, which replace Elementor Pro's Theme
   Builder and Loop Grid. Scoped to .opuae-art / .opuae-arc.
   ========================================================================== */
.opuae-art__wrap{max-width:var(--opuae-max);margin:0 auto;padding-left:var(--opuae-gutter);padding-right:var(--opuae-gutter)}

/* hero */
.opuae-art__hero{background:var(--opuae-black);color:var(--opuae-white);padding:clamp(40px,6vw,88px) 0 clamp(36px,5vw,72px);position:relative;overflow:hidden}
.opuae-art__hero::before{content:"";position:absolute;width:44vw;height:44vw;max-width:580px;max-height:580px;right:-10vw;top:-14vw;background:radial-gradient(circle,rgba(225,6,0,.3),transparent 68%);filter:blur(80px);pointer-events:none}
.opuae-art__crumb{list-style:none;margin:0 0 24px;padding:0;display:flex;flex-wrap:wrap;gap:8px;font-size:13.5px;color:#8A8A92;position:relative}
/* 24px minimum target (WCAG 2.2, 2.5.8). inline-block so vertical
   padding counts toward the box, negative margin so the layout does
   not move: the hit area grows and nothing looks different. */
.opuae-art__crumb a{display:inline-block;padding:4px 0;margin:-4px 0;color:#8A8A92;text-decoration:none;transition:color var(--opuae-t) var(--opuae-ease)}
.opuae-art__crumb a:hover{color:var(--opuae-red)}
.opuae-art__crumb li+li::before{content:"/";margin-right:8px}
.opuae-art__cat{display:inline-block;position:relative;font-family:var(--opuae-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--opuae-red-text);border:1px solid rgba(225,6,0,.45);padding:5px 11px;margin-bottom:18px;text-decoration:none;transition:background var(--opuae-t) var(--opuae-ease),color var(--opuae-t) var(--opuae-ease)}
.opuae-art__cat:hover{background:var(--opuae-red);color:#fff}
.opuae-art__seal{display:inline-block;position:relative;font-family:var(--opuae-mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;border:1px solid currentColor;padding:6px 13px;margin-bottom:18px}
.opuae-art__hero h1{position:relative;font-family:var(--opuae-display);font-weight:700;font-size:clamp(30px,4.8vw,66px);line-height:1.02;letter-spacing:-.02em;text-transform:uppercase;margin:0;max-width:22ch;color:#fff}
.opuae-art__vline{position:relative;margin:18px 0 0;font-size:clamp(16px,1.35vw,20px);line-height:1.55;color:#C9C9CF;max-width:60ch}
.opuae-art__meta{position:relative;display:flex;flex-wrap:wrap;gap:8px 20px;margin:26px 0 0;font-family:var(--opuae-mono);font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:#7C7C85}
.opuae-art__feat{background:var(--opuae-black);padding-bottom:clamp(24px,3vw,44px)}
.opuae-art__feat img{width:100%;height:auto;display:block}

/* body */
.opuae-art__body{background:var(--opuae-white);padding:clamp(44px,6vw,88px) 0}
.opuae-art__grid{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,9fr);gap:clamp(24px,4vw,64px);align-items:start}
.opuae-art__aside{position:sticky;top:120px}
.opuae-art__toc{border-left:2px solid var(--opuae-line);padding-left:18px;margin-bottom:26px}
.opuae-art__toc b{display:block;font-family:var(--opuae-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--opuae-mute);margin-bottom:12px;font-weight:400}
.opuae-art__toc a{display:block;padding:6px 0;font-size:14px;line-height:1.4;color:var(--opuae-mute);text-decoration:none;transition:color var(--opuae-t) var(--opuae-ease),transform var(--opuae-t) var(--opuae-ease)}
.opuae-art__toc a:hover{color:var(--opuae-red);transform:translateX(3px)}
.opuae-art__toc a.is-active{color:var(--opuae-ink);font-weight:600}
.opuae-art__share{border-top:1px solid var(--opuae-line);padding-top:18px;display:flex;flex-direction:column;gap:8px}
.opuae-art__share span{font-family:var(--opuae-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--opuae-mute)}
/* 24px minimum target (WCAG 2.2, 2.5.8). inline-block so vertical
   padding counts toward the box, negative margin so the layout does
   not move: the hit area grows and nothing looks different. */
.opuae-art__share a{display:inline-block;padding:4px 0;margin:-4px 0;font-size:14px;color:var(--opuae-ink);text-decoration:none;transition:color var(--opuae-t) var(--opuae-ease)}
.opuae-art__share a:hover{color:var(--opuae-red)}

/* prose */
.opuae-art__content{max-width:72ch;font-size:clamp(16.5px,1.25vw,18.5px);line-height:1.72;color:var(--opuae-ink);min-width:0;overflow-wrap:anywhere}
.opuae-art__content > p:first-of-type{font-size:1.1em;line-height:1.6}
.opuae-art__content h2{font-family:var(--opuae-display);font-weight:700;font-size:clamp(24px,2.6vw,36px);line-height:1.1;text-transform:uppercase;letter-spacing:-.015em;margin:46px 0 14px;scroll-margin-top:110px}
.opuae-art__content h3{font-size:clamp(19px,1.7vw,23px);font-weight:650;margin:32px 0 10px;scroll-margin-top:110px}
.opuae-art__content h4{font-size:17px;font-weight:650;margin:26px 0 8px}
.opuae-art__content p{margin:0 0 20px}
.opuae-art__content ul,.opuae-art__content ol{margin:0 0 22px;padding-left:0;list-style:none}
.opuae-art__content ol{counter-reset:opa}
.opuae-art__content li{position:relative;padding-left:26px;margin-bottom:10px;line-height:1.6}
.opuae-art__content ul > li::before{content:"";position:absolute;left:0;top:12px;width:11px;height:2px;background:var(--opuae-red)}
.opuae-art__content ol > li{counter-increment:opa}
.opuae-art__content ol > li::before{content:counter(opa);position:absolute;left:0;top:1px;font-family:var(--opuae-mono);font-size:12px;color:var(--opuae-red)}
.opuae-art__content a:not(.opuae-btn){color:var(--opuae-ink);text-decoration:none;border-bottom:2px solid var(--opuae-red);transition:color var(--opuae-t) var(--opuae-ease),background var(--opuae-t) var(--opuae-ease)}
.opuae-art__content a:not(.opuae-btn):hover{color:var(--opuae-red)}
.opuae-art__content strong{font-weight:650}
.opuae-art__content blockquote{margin:30px 0;padding:4px 0 4px 24px;border-left:3px solid var(--opuae-red);font-size:1.12em;line-height:1.5;font-weight:500}
.opuae-art__content blockquote p{margin:0}
.opuae-art__content code{font-family:var(--opuae-mono);font-size:.88em;background:var(--opuae-paper);padding:2px 6px;border:1px solid var(--opuae-line)}
.opuae-art__content img{max-width:100%;height:auto;display:block;margin:28px 0}
.opuae-art__content figure{margin:28px 0;max-width:100%;overflow-x:auto}
.opuae-art__content table{width:100%;border-collapse:collapse;font-size:15px;min-width:420px}
/* An article's table is authored as a bare <table> in post_content, so it has
   no scroll wrapper of its own and min-width:420px put it 48px past a 390px
   phone. opuae-core.js wraps each one at runtime; this is the fallback for
   when that has not run yet or at all. Dropping the floor lets the table
   squeeze instead of bleeding: cramped is survivable, cut off is not.

   display:block would also make it scroll, and is the usual trick, but
   Chrome and Safari drop the table role when a <table> is not display:table,
   so a screen reader stops announcing rows and headers. A wrapper keeps the
   semantics, which is why the fix is a wrapper. */
.opuae-art__scroll{overflow-x:auto;max-width:100%;-webkit-overflow-scrolling:touch}
@media (max-width:480px){
  .opuae-art__content table{min-width:0}
  .opuae-art__scroll table{min-width:420px}
  .opuae-art__content th,.opuae-art__content td{padding:10px;font-size:13.5px}
}
.opuae-art__content th,.opuae-art__content td{text-align:left;padding:12px 14px;border-bottom:1px solid var(--opuae-line);vertical-align:top;line-height:1.5}
.opuae-art__content thead th{background:var(--opuae-black);color:#fff;font-family:var(--opuae-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;font-weight:400;border-bottom:0}
.opuae-art__content tbody tr:hover{background:var(--opuae-paper)}
.opuae-art__disc{margin-top:34px;padding-top:20px;border-top:1px solid var(--opuae-line);font-size:13.5px;line-height:1.6;color:var(--opuae-mute)}

/* reading progress */
.opuae-art__prog{position:fixed;top:0;left:0;height:3px;background:var(--opuae-red);width:0;z-index:950;transition:width 90ms linear}

/* related */
.opuae-art__rel{background:var(--opuae-paper);padding:clamp(44px,6vw,86px) 0}
.opuae-art__rel h2{font-family:var(--opuae-display);font-weight:700;font-size:clamp(24px,2.8vw,38px);text-transform:uppercase;margin:0 0 26px;letter-spacing:-.015em}
.opuae-art__relgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px}
.opuae-art__relcard{display:block;text-decoration:none;color:var(--opuae-ink);background:var(--opuae-white);border:1px solid var(--opuae-line);transition:border-color var(--opuae-t) var(--opuae-ease),transform var(--opuae-t-slow) var(--opuae-ease)}
.opuae-art__relcard:hover{border-color:var(--opuae-ink);transform:translateY(-5px)}
.opuae-art__relimg{display:block;aspect-ratio:16/9;overflow:hidden;background:var(--opuae-paper)}
.opuae-art__relimg img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 600ms var(--opuae-ease)}
.opuae-art__relcard:hover .opuae-art__relimg img{transform:scale(1.04)}
.opuae-art__relcard h3{font-family:var(--opuae-display);font-size:19px;text-transform:uppercase;margin:0;padding:18px 18px 6px;line-height:1.15}
.opuae-art__relcard p{margin:0;padding:0 18px 20px;font-size:14px;line-height:1.55;color:var(--opuae-mute)}

/* ---------- archive ---------- */
.opuae-arc{background:var(--opuae-white);padding:clamp(40px,6vw,92px) 0 clamp(50px,7vw,100px)}
.opuae-arc__head{max-width:62ch;margin-bottom:clamp(26px,3vw,44px)}
.opuae-arc__head h1{font-family:var(--opuae-display);font-weight:700;font-size:clamp(34px,6vw,86px);line-height:.98;text-transform:uppercase;letter-spacing:-.02em;margin:0 0 14px}
.opuae-arc__lede{font-size:clamp(16px,1.3vw,19px);line-height:1.6;color:var(--opuae-mute);margin:0}
.opuae-arc__filters{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:clamp(26px,3vw,40px);padding-bottom:4px}
.opuae-arc__filters a{padding:9px 15px;border:1px solid var(--opuae-line);color:var(--opuae-ink);text-decoration:none;font-size:14px;transition:background var(--opuae-t) var(--opuae-ease),border-color var(--opuae-t) var(--opuae-ease),color var(--opuae-t) var(--opuae-ease)}
.opuae-arc__filters a:hover,.opuae-arc__filters a[aria-current]{background:var(--opuae-black);border-color:var(--opuae-black);color:#fff}
.opuae-arc__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px 22px}
.opuae-arc__card{display:flex;flex-direction:column;text-decoration:none;color:var(--opuae-ink);border:1px solid var(--opuae-line);background:var(--opuae-white);overflow:hidden;transition:border-color var(--opuae-t) var(--opuae-ease),transform var(--opuae-t-slow) var(--opuae-ease),box-shadow var(--opuae-t-slow) var(--opuae-ease)}
.opuae-arc__card:hover{border-color:var(--opuae-ink);transform:translateY(-6px);box-shadow:0 24px 44px -32px rgba(0,0,0,.6)}
.opuae-arc__media{display:block;aspect-ratio:16/9;overflow:hidden;background:var(--opuae-black)}
.opuae-arc__media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 600ms var(--opuae-ease)}
.opuae-arc__card:hover .opuae-arc__media img{transform:scale(1.04)}
.opuae-arc__ph{display:block;width:100%;height:100%;background:linear-gradient(135deg,#141418,#000)}
.opuae-arc__b{display:flex;flex-direction:column;flex:1;padding:20px 20px 22px}
.opuae-arc__tags{display:flex;gap:7px;margin-bottom:12px;min-height:20px}
.opuae-arc__tags em{font-style:normal;font-family:var(--opuae-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--opuae-mute);border:1px solid var(--opuae-line);padding:3px 8px}
.opuae-arc__card h2{font-family:var(--opuae-display);font-size:clamp(20px,1.9vw,24px);text-transform:uppercase;line-height:1.1;margin:0 0 10px;transition:color var(--opuae-t) var(--opuae-ease)}
.opuae-arc__card:hover h2{color:var(--opuae-red)}
.opuae-arc__card p{margin:0 0 18px;font-size:14.5px;line-height:1.58;color:var(--opuae-mute)}
.opuae-arc__go{margin-top:auto;display:inline-flex;align-items:center;gap:9px;font-size:13.5px;font-weight:600;transition:gap var(--opuae-t) var(--opuae-ease)}
.opuae-arc__card:hover .opuae-arc__go{gap:14px;color:var(--opuae-red)}
.opuae-arc__pg{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:clamp(34px,4vw,56px)}
.opuae-arc__pg .page-numbers{display:inline-block;padding:10px 15px;border:1px solid var(--opuae-line);color:var(--opuae-ink);text-decoration:none;font-size:14px;transition:background var(--opuae-t) var(--opuae-ease),color var(--opuae-t) var(--opuae-ease),border-color var(--opuae-t) var(--opuae-ease)}
.opuae-arc__pg .page-numbers:hover,.opuae-arc__pg .page-numbers.current{background:var(--opuae-black);border-color:var(--opuae-black);color:#fff}
.opuae-arc__empty{font-size:17px;color:var(--opuae-mute);padding:40px 0}
.opuae-arc__empty a{color:var(--opuae-ink);border-bottom:2px solid var(--opuae-red);text-decoration:none}

/* ---------- 404 ---------- */
.opuae-404{background:var(--opuae-black);color:#fff;padding:clamp(70px,12vw,170px) 0;min-height:60vh;display:flex;align-items:center}
.opuae-404 h1{font-family:var(--opuae-display);font-weight:700;font-size:clamp(36px,7vw,96px);line-height:.98;text-transform:uppercase;margin:0 0 18px;color:#fff}
.opuae-404 p{color:#A9A9B0;font-size:17px;line-height:1.6;max-width:50ch;margin:0 0 30px}
.opuae-404__links{display:flex;flex-wrap:wrap;gap:11px}

@media (max-width:1023px){
  .opuae-art__grid{grid-template-columns:minmax(0,1fr)}
  .opuae-art__aside{position:static;order:2;margin-top:34px}
  .opuae-art__toc{display:none}
  .opuae-art__content{order:1;max-width:none}
  .opuae-art__relgrid,.opuae-arc__grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:680px){
  .opuae-art__relgrid,.opuae-arc__grid{grid-template-columns:minmax(0,1fr)}
  .opuae-art__share{flex-direction:row;flex-wrap:wrap;gap:14px;align-items:center}
}

/* ---------------------------------------------------------------- case study
   The fact strip sits under the case study headline: sector, location and
   scope, so a reader can place the project before reading it. */
.opuae-cs__facts{list-style:none;margin:0 0 34px;padding:0 0 26px;border-bottom:1px solid var(--opuae-line);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
.opuae-cs__facts li{font-size:15px;line-height:1.5;color:var(--opuae-ink);min-width:0}
.opuae-cs__facts li span{display:block;font-family:var(--opuae-mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--opuae-mute);margin-bottom:7px}
.opuae-cs__note{margin-top:34px;padding-top:20px;border-top:1px solid var(--opuae-line);
  font-size:13px;line-height:1.6;color:var(--opuae-mute)}
@media (max-width:767px){.opuae-cs__facts{grid-template-columns:minmax(0,1fr);gap:14px}}


/* ---------- page hero -------------------------------------------------
   A compact title band for pages composed entirely of section blocks.

   /services/, /commerce/ and /apps/ had no H1 at all: every block they are
   built from opens on an H2, because each one also has to sit under the home
   page's hero. Promoting the first H2 was tried and is wrong, because the
   cards inside that same section are H3s, so the outline jumped H1 to H3.
   These pages needed a heading of their own, and they read better with one.

   Deliberately shorter and quieter than the home and About heroes: it names
   the page and gets out of the way. No photograph, so it never competes with
   the section directly beneath it. */
.opuae-ph{background:var(--opuae-black);color:var(--opuae-white);position:relative;
  overflow:hidden;padding:clamp(44px,6vw,86px) 0 clamp(36px,4.6vw,64px)}
.opuae-ph::before{content:"";position:absolute;width:42vw;height:42vw;
  max-width:520px;max-height:520px;right:-12vw;top:-18vw;
  background:radial-gradient(circle,rgba(225,6,0,.26),transparent 68%);
  filter:blur(80px);pointer-events:none}
.opuae-ph__in{position:relative;max-width:var(--opuae-max);margin:0 auto;
  padding:0 var(--opuae-gutter)}
.opuae-ph h1{font-family:var(--opuae-display);font-weight:700;
  font-size:clamp(34px,5.2vw,72px);line-height:.98;letter-spacing:-.02em;
  text-transform:uppercase;margin:0;color:#fff}
.opuae-ph h1 em{font-style:normal;color:var(--opuae-red-text)}
.opuae-ph__lede{margin:18px 0 0;max-width:60ch;font-size:clamp(15.5px,1.2vw,18px);
  line-height:1.6;color:#C9C9CF}

/* ---------- legal and sitemap pages -----------------------------------
   Privacy, terms, cookies and the sitemap. They reuse .opuae-art__content
   for typography rather than carrying a second set: one body-copy scale on
   the site, not two that drift.

   These pages previously had no wrapper and no page template at all, so the
   theme rendered them in its own defaults and they read as a different
   website. Nothing caught it because the QA suite only ever sees preview/,
   and none of the four had a preview. */
.opuae-legal{background:var(--opuae-white);padding:var(--opuae-sec-y) 0}
.opuae-legal__in{max-width:var(--opuae-max);margin:0 auto;
  padding-left:var(--opuae-gutter);padding-right:var(--opuae-gutter)}
/* A link list is the whole point of the sitemap page, so give the lists room
   and drop the default disc for something quieter. */
.opuae-legal .opuae-art__content ul{list-style:none;padding:0;margin:0 0 30px;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:2px}
/* The article prose styles that must NOT come through here: the red dash
   marker before every <li>, its 26px indent, and the red underline that
   .opuae-art__content puts on every link. Inside a bordered chip each of
   those reads as a rendering fault rather than as styling. Specificity is
   (0,3,2) against the article rules' (0,1,2) and (0,2,1), so these win
   deliberately rather than by source order. */
.opuae-legal .opuae-art__content ul > li{margin:0;padding-left:0}
.opuae-legal .opuae-art__content ul > li::before{content:none}
.opuae-legal .opuae-art__content ul > li > a:not(.opuae-btn){display:block;
  padding:9px 12px;border:0;border-left:2px solid var(--opuae-line);
  text-decoration:none;color:var(--opuae-ink);font-size:15.5px;
  transition:border-color var(--opuae-t) var(--opuae-ease),
             background var(--opuae-t) var(--opuae-ease),
             color var(--opuae-t) var(--opuae-ease)}
.opuae-legal .opuae-art__content ul > li > a:not(.opuae-btn):hover{
  border-left-color:var(--opuae-red);background:var(--opuae-paper);
  color:var(--opuae-red-text)}
/* Terms and privacy are running prose, not link lists: a numbered or bulleted
   clause list there should stay a list. */
.opuae-legal .opuae-art__content ol{margin:0 0 26px 22px}
