/*
Theme Name: Blitzbox
Template: blocksy
Description: Blitzbox design system on Blocksy. style.css below is assets/blitzbox.css from the static build - do not hand-edit here, regenerate from the source.
Version: 1.0.0
*/

/* ==========================================================================
   BLITZBOX — design system
   Every repeated pattern here is a single flat class, so it can be pasted
   into an Elementor element's "CSS Classes" field without nesting or
   specificity fights. Nothing below depends on markup Elementor can't emit.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=JetBrains+Mono:wght@400;500;700&display=swap');

:root {
  /* Light palette, trialled at the client's request (2026-10-03): white
     ground, the Blitzbox Studios Shopify teal for text, #94b9c2 as the
     highlight. The token NAMES are unchanged from the dark build — --ink is
     still "the ground" and --red still "the accent" — so every rule below, and
     the WordPress copy of this file, follows from the values alone. */
  --ink:        #ffffff;   /* page ground */
  --ink-2:      #f1f6f7;   /* raised surface: tiles, form wells */
  --paper:      #103948;   /* primary text */
  --red:        #94b9c2;   /* the one accent — used as solid fill */
  --red-deep:   #7aa5b0;   /* hover / pressed */
  --red-soft:   #dfeaed;   /* accent as a tint: badge, ticker */
  /* The accent is too pale to read as text or as a 1px mark on white (2.1:1),
     so anything drawn IN the accent rather than ON it takes this deeper shade
     of the same hue — 5.3:1 on white. */
  --red-text:   #3f7683;
  /* Teal, not white: white on the pale accent is 2.1:1, under half of what a
     label this small needs (4.5:1). Teal is 5.9:1 on it and 4.6:1 on the hover
     shade, and matches every other accent fill (tabs, .bb-fill). Was #ffffff
     until 23 Oct 2026. */
  --on-red:     #103948;   /* label on a solid accent button */
  --teal:       #103948;   /* the text colour as a constant — see photo heroes */
  --rule:       rgba(16,57,72,0.16);

  --muted:      rgba(16,57,72,0.74);
  --muted-dim:  rgba(16,57,72,0.56);

  /* Client marks and social glyphs are solid black SVGs. On white they need
     nothing; over a photo hero they are inverted to white. */
  --mark-filter: none;
  /* Dropdown panels are white on a white page, so a hairline alone does not
     lift them off the content they open over. */
  --panel-shadow: 0 22px 44px -26px rgba(16,57,72,0.34);

  --sans: "DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Header height, so a full-fold hero can subtract it. Kept in sync with
     .bb-header-in below — it drops to 74px at the burger breakpoint. */
  --header-h: 90px;

  /* One horizontal rhythm for every page. */
  --shell: 1560px;
  --gutter: clamp(20px, 4vw, 64px);
  /* Was 56–104px. The client read the gaps between sections as too large, so
     the band is ~25% tighter at every width. Sections still separate clearly —
     each one opens with a heading over a hairline rule. */
  --band: clamp(42px, 5.2vw, 78px);
}

/* — reset —------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  font-weight: 400;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--red-text); outline-offset: 3px; }
::selection { background: var(--red); color: var(--teal); }

/* Nothing in this system is rounded. The sharp corner is the whole point. */
input, textarea, select, button { border-radius: 0; font: inherit; }

/* The parts of a form the browser draws itself — the dropdown list that opens
   over the page, the date picker, scrollbars — are not reachable from this
   stylesheet. Declaring the scheme keeps them light even for a visitor whose
   OS is in dark mode, so they match the page they sit on. */
:root { color-scheme: light; }

/* — layout —------------------------------------------------------------ */
.bb-shell { width: min(var(--shell), 100%); margin-inline: auto; padding-inline: var(--gutter); }
.bb-band { padding-block: var(--band); }
.bb-band-tight { padding-block: clamp(26px, 3vw, 42px); }
.bb-hr { height: 1px; background: var(--rule); border: 0; margin: 0; }

/* — type —-------------------------------------------------------------- */
/* Display is set tight and heavy. The tracking is lighter than it was for the
   mono face — DM Sans is already narrow, and the old -0.045em closed it up
   until letters touched. */
.bb-display {
  margin: 0;
  /* Floor is 30px, not 38px: Norwegian compounds run long, and the longest
     headline word on the site ("merkevareopplevelser") needs ~30px to fit a
     375px viewport. At the old floor it overflowed and the hero clipped it
     mid-word. Only sub-405px screens ever reach the floor. */
  font-size: clamp(30px, 7.4vw, 96px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  font-weight: 700;
  text-wrap: balance;
  /* Last-resort guard only — with the floor above, no current headline hits
     it. Without it an unexpected long word would be cut off silently rather
     than wrapped, because .bb-hero sets overflow:hidden. */
  overflow-wrap: break-word;
}
.bb-h2 {
  margin: 0;
  font-size: clamp(25px, 3.4vw, 44px);
  line-height: 1.08;
  letter-spacing: -0.025em;
  font-weight: 700;
  text-wrap: balance;
}
.bb-h3 {
  margin: 0;
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.25;
  letter-spacing: -0.012em;
  font-weight: 700;
}
.bb-lead {
  margin: 0;
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.65;
  color: var(--muted);
  max-width: 46ch;
  text-wrap: pretty;
}
/* margin:0 above is deliberate — a lead is normally the only one in its
   block. Where the client's copy runs to two paragraphs they would otherwise
   butt together into a single wall. */
.bb-lead + .bb-lead { margin-top: 1.1em; }
/* Spans the shell rather than stopping at the 46ch measure. For a lead that
   introduces a full-width grid below it, the short measure left a ragged gap
   across the right half of the section. */
.bb-lead-wide { max-width: none; }
.bb-body { margin: 0; color: var(--muted); max-width: 68ch; text-wrap: pretty; }
.bb-body + .bb-body { margin-top: 14px; }

/* The status line. Reads like the data strip along a camera viewfinder —
   wide-tracked, all caps, never more than a few words per segment. */
.bb-status {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px;
  margin: 0 0 clamp(22px, 3vw, 38px);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--muted);
}
.bb-status .bb-dot { width: 5px; height: 5px; background: var(--red-text); flex: none; }
.bb-eyebrow {
  display: block; margin: 0 0 14px;
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--muted-dim);
}
.bb-num { color: var(--red-text); }

/* — links —------------------------------------------------------------- */
.bb-link {
  text-decoration: none;
  background-image: linear-gradient(var(--red-text), var(--red-text));
  background-size: 0 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size .32s cubic-bezier(.2,.7,.2,1);
}
.bb-link:hover, .bb-link:focus-visible { background-size: 100% 1px; }

/* — buttons —----------------------------------------------------------- */
.bb-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 28px; border: 1px solid transparent;
  font-size: 11.5px; font-weight: 700; line-height: 1;
  letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none;
  cursor: pointer;
  transition: background-color .22s, color .22s, border-color .22s;
}
.bb-btn-solid { background: var(--red); color: var(--on-red); }
.bb-btn-solid:hover, .bb-btn-solid:focus-visible { background: var(--red-deep); }
/* The outline is the accent itself rather than a hairline rule, so the ghost
   buttons read as part of the same set as the filled one beside them. */
.bb-btn-ghost { background: transparent; color: var(--paper); border-color: var(--red); }
.bb-btn-ghost:hover, .bb-btn-ghost:focus-visible { border-color: var(--paper); }
.bb-arrow { transition: transform .3s cubic-bezier(.2,.7,.2,1); }
.bb-btn:hover .bb-arrow, .bb-frame:hover .bb-arrow { transform: translateX(6px); }
.bb-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* — the contact sheet —-------------------------------------------------- */
/* The signature. Tiles sit on a hairline grid like frames on a strip of
   negatives, and each one numbers itself with a CSS counter — so in
   Elementor you add .bb-sheet to the container and .bb-frame to the
   children, and the numbering just happens. No data attributes, no HTML
   widget, nothing to keep in sync by hand. */
.bb-sheet {
  counter-reset: frame;
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
}
.bb-sheet-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.bb-sheet-wide { grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); }

.bb-frame {
  counter-increment: frame;
  position: relative;
  display: flex; flex-direction: column;
  background: var(--ink);
  padding: clamp(20px, 2.2vw, 30px);
  text-decoration: none; color: inherit;
  transition: background-color .28s;
}
.bb-frame::before {
  content: counter(frame, decimal-leading-zero);
  position: absolute; top: 12px; right: 14px;
  font-size: 10px; font-weight: 500; letter-spacing: 0.16em;
  color: var(--muted-dim);
  transition: color .28s;
}
a.bb-frame:hover, a.bb-frame:focus-visible { background: var(--ink-2); }
a.bb-frame:hover::before, a.bb-frame:focus-visible::before { color: var(--red-text); }
.bb-frame-foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin-top: auto; padding-top: 22px;
}
/* Suppress numbering where the grid is a plain layout, not a sheet. */
.bb-sheet-plain { counter-reset: none; }
.bb-sheet-plain .bb-frame::before { content: none; }

/* Image-topped frame: the picture is the frame, caption sits beneath. */
.bb-shot { position: relative; overflow: hidden; background: var(--ink-2); aspect-ratio: 4 / 3; }
.bb-shot-sq { aspect-ratio: 1 / 1; }
.bb-shot-tall { aspect-ratio: 3 / 4; }
.bb-shot img { width: 100%; height: 100%; object-fit: cover; transition: transform .7s cubic-bezier(.2,.7,.2,1); }
.bb-frame:hover .bb-shot img, a:hover .bb-shot img { transform: scale(1.05); }
.bb-frame-media { padding: 0; }
.bb-frame-media .bb-frame-body { padding: clamp(18px, 2vw, 26px); }
/* White, not the page's text colour: `difference` only inverts the photo
   beneath it when the glyph itself is light. Dark teal subtracted almost
   nothing and the counter disappeared into the picture. */
.bb-frame-media::before { top: 12px; right: 14px; z-index: 2; mix-blend-mode: difference; color: #fff; }
a.bb-frame-media:hover::before, a.bb-frame-media:focus-visible::before { color: #fff; }

/* — rail (horizontal sheet) —-------------------------------------------- */
/* A .bb-sheet lays out with auto-fit, so any count that does not divide by the
   column count leaves dead cells — five segments in a four-wide grid shows one
   card beside three empty ones. This is the same sheet turned on its side: the
   cards keep their width and the row scrolls instead of wrapping.

   flex-grow:1 with a fixed basis is what makes it safe to use everywhere. With
   MORE cards than fit, the basis holds and the row overflows into a scroll.
   With FEWER, they grow to fill the width — so a short rail never reopens the
   very gap this is here to close. */
.bb-rail {
  --rail-cols: 4;
  counter-reset: frame;
  display: flex;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  overflow-x: auto;
  /* Naming only overflow-x makes the other axis compute to auto as well, so the
     rail became scrollable vertically under the pointer even though nothing
     overflows it - the gutter alone was enough. */
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;              /* the arrows are the affordance */
}
.bb-rail::-webkit-scrollbar { display: none; }
.bb-rail > .bb-frame {
  flex: 1 0 calc((100% - (var(--rail-cols) - 1) * 1px) / var(--rail-cols));
  min-width: 0;
  scroll-snap-align: start;
}
/* A scrollable region must be reachable by keyboard on its own, since the
   cards inside can be plain tiles with nothing focusable. */
.bb-rail:focus-visible { outline: 2px solid var(--red-text); outline-offset: 3px; }
@media (max-width: 1180px) { .bb-rail { --rail-cols: 3; } }
@media (max-width: 860px)  { .bb-rail { --rail-cols: 2; } }
@media (max-width: 560px)  { .bb-rail { --rail-cols: 1; } }

/* Sits in .bb-head next to the section's "see all" link. Hidden by script
   when the rail does not actually overflow — arrows that cannot move are
   worse than no arrows. */
.bb-head-end { display: flex; align-items: center; gap: clamp(14px, 1.6vw, 24px); align-self: center; }
.bb-rail-nav { display: inline-flex; gap: 6px; }
.bb-rail-btn {
  width: 36px; height: 36px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--rule); color: var(--muted);
  padding: 0; cursor: pointer;
  transition: color .2s, background-color .2s, border-color .2s, opacity .2s;
}
.bb-rail-btn:hover:not(:disabled) { background: var(--red); border-color: var(--red); color: var(--teal); }
.bb-rail-btn:disabled { opacity: .28; cursor: default; }
/* currentColor so the glyph follows the button straight through the hover
   swap; 1.6 keeps the stroke close to the 1px rules it sits among without
   disappearing at this size. */
.bb-chev {
  width: 15px; height: 15px; display: block;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: square; stroke-linejoin: miter;
}

/* — ticker —------------------------------------------------------------ */
/* Tinted band. Two identical runs slide as one so the loop is seamless.
   The tint rather than the solid accent: dark text on the pale wash reads at
   11:1, where white on the solid accent would be 2.1:1 at 11.5px. */
.bb-ticker { background: var(--red-soft); color: var(--teal); overflow: hidden; padding-block: 13px; }
.bb-ticker-track { display: flex; width: max-content; animation: bb-slide 42s linear infinite; }
.bb-ticker-run { display: flex; align-items: center; flex: none; }
.bb-ticker-run span {
  padding-inline: 26px;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase; white-space: nowrap;
}
@keyframes bb-slide { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }


/* — stat row —---------------------------------------------------------- */
.bb-stats {
  display: grid; gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.bb-stat { background: var(--ink); padding: clamp(22px, 2.4vw, 32px); }
.bb-stat-val {
  display: block;
  font-size: clamp(26px, 3vw, 40px); font-weight: 700;
  letter-spacing: -0.03em; line-height: 1;
}
.bb-stat-key {
  display: block; margin-top: 10px;
  font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted-dim);
}

/* — spec rows —--------------------------------------------------------- */
/* Label left, value right, hairline between. Used for kit lists, case
   metadata and anywhere a fact needs a name. */
.bb-specs { border-top: 1px solid var(--rule); }
.bb-spec {
  display: grid; gap: 6px 28px;
  grid-template-columns: minmax(120px, 200px) 1fr;
  padding: 17px 0;
  border-bottom: 1px solid var(--rule);
}
.bb-spec-key {
  font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-dim);
  padding-top: 4px;
}
.bb-spec-val { margin: 0; color: var(--paper); }

/* — split —------------------------------------------------------------- */
.bb-split { display: grid; gap: clamp(28px, 4vw, 72px); grid-template-columns: minmax(0,1fr) minmax(0,1fr); align-items: start; }
.bb-split-wide { grid-template-columns: minmax(0,1.4fr) minmax(0,0.6fr); }
.bb-split-narrow { grid-template-columns: minmax(0,0.6fr) minmax(0,1.4fr); }
.bb-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 14px 26px; padding-bottom: 20px; margin-bottom: clamp(24px, 3vw, 40px);
  border-bottom: 1px solid var(--rule);
}

/* — quotes —------------------------------------------------------------ */
/* margin:0 because the card is a <figure> — the UA's default 40px side margin
   otherwise floats it inside the sheet's border with a grey band around it. */
.bb-quote { background: var(--ink); padding: clamp(24px, 2.6vw, 36px); margin: 0; display: flex; flex-direction: column; }
.bb-quote-text { margin: 0 0 22px; font-size: clamp(16px, 1.4vw, 19px); line-height: 1.6; letter-spacing: -0.005em; }
.bb-quote-by { margin-top: auto; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted-dim); }
.bb-quote-by strong { display: block; color: var(--paper); font-weight: 500; letter-spacing: 0.1em; margin-bottom: 3px; }

/* — quote slider —------------------------------------------------------- */
/* One testimonial at a time, cycling, with dots — the client's old site had
   this and asked to keep it. Slides stack in a 1x1 grid rather than absolute
   positioning, so the box is as tall as the LONGEST quote and the section
   never changes height as it rotates.

   Only the active slide is in the a11y tree and the tab order: a screen reader
   should not read eight quotes as one run-on paragraph, and Tab should not
   travel through hidden text. chrome.js owns .is-on and the inert siblings. */
/* Gated on .is-live, which chrome.js sets once it has wired the dots. Without
   the gate a reader with JS off would get one quote and no way to reach the
   rest; this way they get all of them, stacked, as before.

   Three across on a wide screen — chrome.js sets --q-per to 3 / 2 / 1 and
   shows one page at a time. Off-page quotes are display:none so the row lays
   out around only the visible ones; the container carries a min-height set
   from the tallest page, so advancing never jolts the page. */
.bb-quotes.is-live {
  grid-template-columns: repeat(var(--q-per, 1), minmax(0, 1fr));
  align-items: stretch;
}
.bb-quotes.is-live > .bb-quote { display: none; }
.bb-quotes.is-live > .bb-quote.is-on {
  display: flex;
  animation: bb-quote-in .45s ease both;
}
@keyframes bb-quote-in { from { opacity: 0; } to { opacity: 1; } }

/* Set like the copy in a case card — left-aligned, body size, muted — so the
   testimonial row reads as part of the same system as the "Utvalgte
   prosjekter" cards above it rather than as a pull-quote in a different voice.
   (Matches .bb-frame-copy: 16px body, var(--muted).) */
.bb-quotes .bb-quote { align-items: flex-start; text-align: left; padding-block: clamp(24px, 2.6vw, 34px); }
.bb-quotes .bb-quote-text {
  max-width: none;
  font-size: 16px; line-height: 1.65; letter-spacing: 0;
  color: var(--muted);
}
/* One per view still gets a slightly larger measure — it has the row to
   itself, and at body size alone in a full-width box it looks stranded. */
.bb-quotes.is-live[style*="--q-per: 1"] .bb-quote-text { font-size: clamp(16.5px, 1.3vw, 18.5px); max-width: 70ch; }

.bb-dots { display: flex; justify-content: center; gap: 10px; margin-top: clamp(18px, 2vw, 26px); }
/* Hit area is 22px even though the dot reads as 8px — a bare 8px target fails
   on touch. Hence the transparent padding rather than a bigger dot. */
.bb-dots button {
  width: 22px; height: 22px; padding: 0;
  display: grid; place-items: center;
  background: none; border: 0; cursor: pointer;
}
.bb-dots button::before {
  content: ''; width: 8px; height: 8px;
  background: var(--red);
  transition: background-color .2s, transform .2s;
}
/* Resting dots are the pale accent and the current one is full-strength text
   colour — on white the accent is the quieter of the two, so the old
   "accent = current" pairing would have marked the wrong dot. */
.bb-dots button:hover::before { background: var(--red-text); }
.bb-dots button[aria-current="true"]::before { background: var(--paper); transform: scale(1.25); }

/* — forms —------------------------------------------------------------- */
/* Styled on bare inputs so a Contact Form 7 / Fluent Forms shortcode picks
   the look up without per-field configuration. */
.bb-form { display: grid; gap: 18px; }
.bb-field { display: grid; gap: 7px; }
.bb-field label, .bb-label {
  font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted);
}
.bb-form input[type="text"], .bb-form input[type="email"], .bb-form input[type="tel"],
.bb-form input[type="date"], .bb-form select, .bb-form textarea {
  width: 100%; padding: 13px 15px;
  background: var(--ink-2); color: var(--paper);
  border: 1px solid var(--rule);
  transition: border-color .2s;
}
.bb-form textarea { min-height: 132px; resize: vertical; }
/* Label and its hint on one row: the guidance is read on the way INTO the
   field rather than found underneath it afterwards. Baseline-aligned so the
   caps label and the sentence-case hint sit on the same line, and allowed to
   wrap so a long hint drops below the label on a narrow field instead of
   squeezing it. */
.bb-field-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 4px 12px;
}
/* Side by side, one field's label may run to one line and its neighbour's
   label-plus-hint to two. Packing each field's rows to the bottom keeps the
   two inputs on the same line rather than stepping down from each other.

   align-self is what makes that work: .bb-split sets align-items:start, so
   without this each field is only as tall as its own content and align-content
   has no free space to pack into — the shorter field kept its input 33px above
   its neighbour's. Stretching it to the row's height gives align-content
   something to work with. */
.bb-split > .bb-field { align-self: stretch; align-content: end; }
/* Sentence case on purpose — the labels are wide-tracked caps, and guidance in
   that treatment reads as a second heading. No max-width: the hint takes the
   room left on the row, which is what keeps it to a single line. */
.bb-hint {
  font-size: 13px; line-height: 1.55; color: var(--muted-dim);
  letter-spacing: 0; text-transform: none;
  /* basis 0, not auto: with auto the hint's natural width is measured first
     and flex wraps it onto its own line the moment it does not fit. From 0 it
     takes whatever the label leaves and wraps its TEXT instead, which is what
     keeps it on the label's row. */
  flex: 1 1 0; min-width: 12ch;
}
/* Firefox draws the option list from the page's own colours rather than from
   color-scheme, so state them outright as well. Chrome and Safari take these
   too, so the list matches the field it drops out of on all three. */
.bb-form select option { background: var(--ink-2); color: var(--paper); }
.bb-form select option:checked { background: var(--red); color: var(--paper); }
.bb-form input:hover, .bb-form textarea:hover, .bb-form select:hover { border-color: var(--muted-dim); }
.bb-form input:focus, .bb-form textarea:focus, .bb-form select:focus { outline: none; border-color: var(--red-text); }
.bb-form ::placeholder { color: var(--muted-dim); }

/* Checkbox / radio pills. */
.bb-choices { display: flex; flex-wrap: wrap; gap: 8px; }
.bb-choice {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 16px; border: 1px solid var(--rule); cursor: pointer;
  font-size: 14px; transition: border-color .2s, color .2s, background-color .2s;
}
.bb-choice:hover { border-color: var(--muted-dim); }
.bb-choice input { accent-color: var(--red-text); margin: 0; }
/* Picked pills fill with the tint as well as taking the deeper border — a
   border change alone is a thin signal on a white page. */
.bb-choice:has(input:checked) { border-color: var(--red-text); background: var(--red-soft); }
.bb-consent { display: flex; gap: 11px; align-items: flex-start; font-size: 14px; color: var(--muted); line-height: 1.6; }
.bb-consent input { accent-color: var(--red-text); margin-top: 3px; flex: none; }
.bb-note { margin: 0; font-size: 13px; color: var(--muted-dim); }

/* — logo wall —--------------------------------------------------------- */
.bb-logos { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.bb-logos span {
  background: var(--ink); padding: 26px 16px; text-align: center;
  font-size: 12px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted-dim); transition: color .25s;
}
.bb-logos span:hover { color: var(--paper); }

/* — header (the Novamira theme owns this in WordPress) —---------------- */
.bb-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,0.9); backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(16,57,72,0.1);
}
/* Three-column grid so the nav is optically centred in the header rather
   than pushed against the CTA. Runs edge-to-edge — not inside .bb-shell. */
.bb-header-in {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  height: 90px; width: 100%;
  padding-inline: clamp(20px, 2.6vw, 48px);
}
.bb-logo { justify-self: start; display: flex; align-items: center; text-decoration: none; }
.bb-logo img { height: 42px; width: auto; }
.bb-nav { justify-self: center; display: flex; align-items: center; gap: clamp(18px, 2.4vw, 38px); }
.bb-header-end { justify-self: end; display: flex; align-items: center; gap: 10px; }
.bb-nav > a, .bb-dd > a, .bb-dd > button {
  background: none; border: 0; padding: 33px 0; cursor: pointer;
  font-family: var(--mono); font-size: 12px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
  text-decoration: none; transition: color .2s;
}
.bb-nav > a:hover, .bb-dd > a:hover, .bb-dd > button:hover { color: var(--paper); }
.bb-dd { position: relative; display: flex; align-items: center; }
.bb-dd-menu {
  position: absolute; top: 100%; left: -16px; min-width: 244px;
  background: var(--ink); border: 1px solid var(--rule); padding: 6px;
  box-shadow: var(--panel-shadow);
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .2s, transform .2s, visibility .2s;
}
.bb-dd:hover .bb-dd-menu, .bb-dd:focus-within .bb-dd-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.bb-dd-menu a {
  padding: 10px 13px; font-size: 14px; text-decoration: none; color: var(--muted);
  transition: background-color .18s, color .18s;
}
.bb-dd-menu a:hover { background: var(--ink-2); color: var(--paper); }
.bb-burger { display: none; background: none; border: 1px solid var(--rule); color: var(--paper); padding: 10px 13px; cursor: pointer; font-family: var(--mono); font-size: 11px; letter-spacing: .14em; }

/* — photo hero —--------------------------------------------------------- */
/* The client docs all say "place a strong photo background", so the segment
   photograph sits behind the headline rather than in a band beneath it.

   The image is a real <img> (not background-image) so the browser can
   prioritise it as the LCP element and pick it up in object-fit. alt is empty
   because the <h1> already carries the meaning — it is scenery, not content. */
.bb-hero { position: relative; isolation: isolate; overflow: hidden; background: var(--ink); }
.bb-hero-bg { position: absolute; inset: 0; z-index: -1; }
.bb-hero-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* A hero with a photograph behind it is the one place the page is still dark:
   copy cannot sit on a photo without a scrim, and a white scrim strong enough
   to carry dark text bleaches the picture to nothing. So the scrim stays dark
   — tinted to the brand teal rather than black — and the tokens are re-pointed
   for everything inside, which flips the text, rules, ghost buttons and marks
   to their light-on-dark values without a second set of rules.

   Keyed on :has(.bb-hero-bg), so a hero WITHOUT a photo (the homepage) is
   simply part of the white page. */
.bb-hero:has(.bb-hero-bg) {
  --paper:     #fcfcfc;
  --muted:     rgba(252,252,252,0.8);
  --muted-dim: rgba(252,252,252,0.6);
  --rule:      rgba(252,252,252,0.26);
  --red-text:  var(--red);
  --mark-filter: invert(1);
  background: #0a2832;
  color: var(--paper);
}
/* Two scrims, not one: the vertical pass lifts the text off a busy sky, the
   horizontal pass keeps the left column dark enough to hold body copy at any
   crop. Tuned so the darkest point stays well above 7:1 against the text. */
.bb-hero-bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(90deg, rgba(8,32,41,0.94) 0%, rgba(8,32,41,0.82) 42%, rgba(8,32,41,0.42) 100%),
    linear-gradient(180deg, rgba(8,32,41,0.80) 0%, rgba(8,32,41,0.30) 38%, rgba(8,32,41,0.88) 100%);
}
.bb-hero-in {
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: clamp(480px, 64vh, 760px);
  padding-block: clamp(56px, 7vw, 104px);
}

/* Laptop and up, the whole hero has to fit on screen — the logo wall is the
   proof line, and on a 1440x760 laptop it used to sit 187px below the fold.

   Everything above sized on WIDTH only, so a wide-but-short laptop got a 96px
   headline over 200px of padding in a 670px space. These caps add the missing
   dimension: each value is the smaller of the existing width-based size and a
   share of the viewport HEIGHT. On a tall monitor the height term is the
   larger of the two, so nothing changes there — this only bites when vertical
   space is actually short.

   Held above 700px on purpose: a phone scrolls, and capping type against a
   short portrait viewport would shrink the headline for no reason. */
@media (min-width: 700px) {
  .bb-hero-in {
    /* Fills the first screen, the way the homepage hero does — the client
       asked for the same arrival on the subpages. The caps below are what
       make that safe: they keep the whole block, logo wall included, inside
       the screen it now claims, so "full height" never means "scroll to see
       the rest of the hero". */
    min-height: calc(100vh - var(--header-h));
    min-height: calc(100svh - var(--header-h));
    padding-block: clamp(34px, 4.4svh, 104px);
  }
  .bb-hero .bb-display { font-size: min(clamp(30px, 7.4vw, 96px), 9.4svh); }
  .bb-hero .bb-lead { font-size: min(clamp(16px, 1.25vw, 18px), 2.4svh); }
  .bb-hero .bb-hero-proof { margin-top: clamp(14px, 2.4svh, 44px); }
  .bb-hero .bb-actions { margin-top: clamp(16px, 2.6svh, 34px); }
}
/* Body copy over a photograph needs a little more weight than on flat ground. */
.bb-hero:has(.bb-hero-bg) .bb-lead { color: rgba(252,252,252,0.9); }
@media (max-width: 700px) {
  .bb-hero-in { min-height: clamp(420px, 72vh, 560px); }
  /* Portrait crops put the subject centre-frame; bias the crop upward so a
     face is not sliced by the copy sitting at the bottom. */
  .bb-hero-bg img { object-position: 50% 30%; }
}

/* — small-screen drawer —------------------------------------------------ */
/* The panel the burger opens. Sits under the sticky header and takes the rest
   of the viewport, scrolling internally when the segment list is long. Hidden
   outright above the breakpoint so the desktop nav is the only menu there. */
.bb-drawer {
  position: fixed; left: 0; right: 0; top: 74px; bottom: 0;
  z-index: 55;
  background: var(--ink);
  border-top: 1px solid var(--rule);
  overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.bb-drawer[hidden] { display: none; }
@media (min-width: 1101px) { .bb-drawer { display: none !important; } }
body.bb-menu-open { overflow: hidden; }

.bb-drawer-in { display: flex; flex-direction: column; padding: 8px clamp(20px, 5vw, 32px) 40px; }

/* Top-level rows — links and group triggers share one look. */
.bb-drawer-link,
.bb-drawer-group > summary {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 2px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 13px; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--paper); text-decoration: none;
  cursor: pointer; list-style: none;
}
.bb-drawer-group > summary::-webkit-details-marker { display: none; }
.bb-drawer-group > summary::after {
  content: "+"; font-size: 16px; color: var(--red-text); line-height: 1;
}
.bb-drawer-group[open] > summary::after { content: "–"; }

/* Sub-links sit indented and quieter, so the group reads as one unit. */
.bb-drawer-links { display: flex; flex-direction: column; padding: 4px 0 14px; }
.bb-drawer-links a {
  padding: 11px 2px 11px 16px;
  font-size: 15.5px; color: var(--muted); text-decoration: none;
  border-left: 1px solid var(--rule); margin-left: 2px;
}
.bb-drawer-links a:hover, .bb-drawer-links a:focus-visible { color: var(--paper); }
.bb-drawer-head {
  padding: 14px 2px 6px 16px; margin-left: 2px;
  border-left: 1px solid var(--rule);
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted-dim);
}
.bb-drawer-cta { margin-top: 24px; justify-content: center; }

/* — mega menu —---------------------------------------------------------- */
/* The services dropdown is a contact sheet: the same hairline grid the page
   body uses, shrunk into the header. Spans the full header width to match the
   edge-to-edge header rather than hanging off the menu item. */
.bb-dd-mega { position: static; } /* so the panel resolves against .bb-header */
.bb-mega {
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--ink);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  box-shadow: var(--panel-shadow);
  padding: clamp(18px, 2vw, 30px) clamp(20px, 2.6vw, 48px);
  display: grid; gap: clamp(18px, 2.2vw, 36px);
  grid-template-columns: minmax(200px, 250px) 1fr;
  opacity: 0; visibility: hidden; transform: translateY(-7px);
  transition: opacity .26s cubic-bezier(.2,.7,.2,1),
              transform .26s cubic-bezier(.2,.7,.2,1),
              visibility .26s;
}
.bb-dd-mega:hover .bb-mega,
.bb-dd-mega:focus-within .bb-mega,
.bb-dd-mega.is-open .bb-mega { opacity: 1; visibility: visible; transform: translateY(0); }

/* Escape must close the panel — but closing it returns focus to the trigger,
   which sits inside :focus-within and would immediately reopen it. This
   dismissed state wins on source order (equal specificity) and is cleared as
   soon as the pointer or focus genuinely leaves. */
.bb-dd-mega.is-dismissed .bb-mega { opacity: 0; visibility: hidden; transform: translateY(-7px); }

.bb-mega-promo {
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  border-right: 1px solid var(--rule);
  padding-right: clamp(16px, 2vw, 30px);
}
.bb-mega-promo p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--muted); }

/* Fixed columns, not auto-fit: there are exactly 12 services, so 4 columns
   give a clean 4×3 and 3 columns a clean 3×4. auto-fit produced 8+4 and 5+5+2
   at wide viewports, which reads as an accident rather than a grid. */
.bb-mega-grid {
  display: grid; gap: 1px;
  background: var(--rule); border: 1px solid var(--rule);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1240px) {
  .bb-mega-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.bb-mega-tile {
  display: grid; grid-template-columns: 42px 1fr; gap: 11px; align-items: center;
  background: var(--ink); padding: 9px 12px;
  text-decoration: none; color: var(--paper);
  transition: background-color .2s;
}
.bb-mega-tile:hover, .bb-mega-tile:focus-visible { background: var(--ink-2); }
.bb-mega-thumb { width: 42px; aspect-ratio: 1 / 1; overflow: hidden; background: var(--ink-2); }
.bb-mega-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s cubic-bezier(.2,.7,.2,1); }
.bb-mega-tile:hover .bb-mega-thumb img { transform: scale(1.08); }
.bb-mega-name { font-size: 14px; line-height: 1.25; font-weight: 500; }
.bb-mega-cat {
  display: block; margin-top: 3px;
  font-size: 9.5px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted-dim);
}
.bb-caret { transition: transform .24s; }
.bb-dd-mega:hover .bb-caret, .bb-dd-mega:focus-within .bb-caret { transform: rotate(180deg); }

/* — footer (the Novamira theme owns this too) —------------------------- */
.bb-footer { border-top: 1px solid var(--rule); }
.bb-footer-grid { display: grid; gap: clamp(28px, 4vw, 56px); grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); padding-block: clamp(44px, 5vw, 76px); }
.bb-footer h4 { margin: 0 0 16px; font-size: 10.5px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted-dim); }
.bb-footer-col { display: flex; flex-direction: column; gap: 10px; }
.bb-footer-col a { font-size: 14.5px; text-decoration: none; color: var(--paper); }
/* A column flex container stretches its children across the cross axis, which
   distorts the logo (width:auto loses to the stretch) and makes each link the
   full column width — so the bb-link hover underline ran the whole column.
   Images and links size to their own content; paragraphs still stretch, which
   is what text wants.

   Direct children only: unscoped, this also caught the img inside each
   .bb-social anchor, which overrode that anchor's own place-items:center and
   pinned the icon to the top of its 34px box (1px above, 17px below). The
   logo and the footer links are all direct children, so the child combinator
   keeps the intent and stops it reaching the icons. */
.bb-footer-col > img, .bb-footer-col > a { align-self: flex-start; }
.bb-footer-logo { height: 32px; width: auto; margin-bottom: 6px; }
.bb-footer-note { line-height: 1.65; }
.bb-footer-social { margin-top: 8px; }
.bb-footer-more { color: var(--muted); }
/* At the default 28px side padding this button is ~198px — wider than the
   ~190px footer column, so the label wrapped to two lines. Tighter padding
   keeps it on one. */
.bb-footer-cta { margin-top: 8px; padding-inline: 18px; white-space: nowrap; }
.bb-footer-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px;
  padding-block: 20px 36px; border-top: 1px solid var(--rule);
  font-size: 11px; letter-spacing: 0.1em; color: var(--muted-dim);
}
.bb-social { display: flex; gap: 8px; }
.bb-social a {
  display: grid; place-items: center; width: 34px; height: 34px;
  border: 1px solid var(--rule); font-size: 10px; letter-spacing: 0.06em;
  text-decoration: none; color: var(--muted); transition: border-color .2s, color .2s;
}
.bb-social a:hover { border-color: var(--red-text); color: var(--red-text); }
/* The social glyphs ship with no fill, so they paint black — right for the
   white footer as they are, dimmed to sit with the text. Same treatment as
   .bb-mark img. */
.bb-social a img { width: 16px; height: 16px; filter: var(--mark-filter); opacity: .6; transition: opacity .2s; }
.bb-social a:hover img { opacity: 1; }

/* — closing CTA band —--------------------------------------------------- */
/* The accent block that closes most pages. One class instead of five inline
   overrides, so in Elementor it is: Container + .bb-cta-band, done.

   Text on the accent is the dark teal, not white: this band carries a
   paragraph of body copy, and teal on #94b9c2 is 5.9:1 where white is 2.1:1. */
.bb-cta-band {
  background: var(--red); color: var(--teal);
  padding: clamp(32px, 4vw, 64px);
  border: 1px solid var(--red);
}
.bb-cta-band .bb-h2 { max-width: 20ch; }
.bb-cta-band p { margin: 18px 0 0; max-width: 48ch; color: rgba(16,57,72,0.86); }
.bb-btn-invert { background: var(--teal); color: #fff; }
.bb-btn-invert:hover, .bb-btn-invert:focus-visible { background: #0a2832; }
.bb-btn-onred { background: transparent; color: var(--teal); border-color: rgba(16,57,72,0.45); }
.bb-btn-onred:hover, .bb-btn-onred:focus-visible { border-color: var(--teal); }

/* The small uppercase "see all" link that sits in section heads. */
.bb-more {
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; white-space: nowrap;
}
/* Body copy directly under a heading inside a frame. */
.bb-frame-copy { margin: 12px 0 0; color: var(--muted); }
/* Single-column sheet (used for the CTA band and full-width quotes). */
.bb-sheet-1 { grid-template-columns: minmax(0, 1fr); }
.bb-arrow-red { color: var(--red-text); }

/* — utilities —--------------------------------------------------------- */
.bb-fill { background: var(--red); color: var(--teal); }
.bb-fill .bb-stat-key, .bb-fill .bb-eyebrow { color: rgba(16,57,72,0.8); }
.bb-surface { background: var(--ink-2); }
.bb-muted { color: var(--muted); }
.bb-mt { margin-top: clamp(24px, 3vw, 40px); }

/* — responsive —-------------------------------------------------------- */
@media (max-width: 900px) {
  .bb-split, .bb-split-wide, .bb-split-narrow { grid-template-columns: minmax(0,1fr); }
  .bb-spec { grid-template-columns: minmax(0,1fr); }
}
@media (max-width: 980px) {
  .bb-header-in { height: 74px; }
  .bb-nav { display: none; }
  .bb-burger { display: inline-flex; }
}
@media (max-width: 560px) {
  /* Below this the CTA and the burger start colliding; the burger wins. */
  .bb-header-end .bb-btn-solid { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .bb-ticker-track { animation: none; }
  /* chrome.js makes the same call for the quote slider: no auto-advance, dots
     still work. (The results strip needs nothing here — it is static now.) */
  * { transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
}

/* — For bedrifter dropdown —--------------------------------------------- */
.bb-dd-seg { position: static; }
.bb-segmenu {
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--ink);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  box-shadow: var(--panel-shadow);
  padding: clamp(18px, 2vw, 30px) clamp(20px, 2.6vw, 48px);
  display: grid; gap: 1px; grid-template-columns: repeat(3, 1fr);
  opacity: 0; visibility: hidden; transform: translateY(-7px);
  transition: opacity .26s cubic-bezier(.2,.7,.2,1),
              transform .26s cubic-bezier(.2,.7,.2,1), visibility .26s;
}
.bb-dd-seg:hover .bb-segmenu,
.bb-dd-seg:focus-within .bb-segmenu,
.bb-dd-seg.is-open .bb-segmenu { opacity: 1; visibility: visible; transform: translateY(0); }
.bb-dd-seg.is-dismissed .bb-segmenu { opacity: 0; visibility: hidden; transform: translateY(-7px); }
.bb-mega-col { display: flex; flex-direction: column; gap: 2px; padding-right: 24px; }
.bb-mega-colhead {
  font-size: 10px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--red-text); margin-bottom: 10px;
}
.bb-mega-col a {
  padding: 7px 0; font-size: 14.5px; color: var(--muted);
  text-decoration: none; transition: color .18s;
}
.bb-mega-col a:hover { color: var(--paper); }

/* — client logo wall (real marks, monochrome) —-------------------------- */
.bb-marks {
  display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(126px, 1fr));
}
.bb-mark { background: var(--ink); display: grid; place-items: center; padding: 26px 18px; }
.bb-mark img {
  width: auto; height: 26px; max-width: 100%;
  /* SVGs are solid black: left as they are on white, inverted over a photo
     hero (--mark-filter), dimmed, then brought to full on hover. */
  filter: var(--mark-filter); opacity: .5;
  transition: opacity .28s;
}
.bb-mark:hover img { opacity: 1; }

/* — FAQ accordion (native <details>, no JS) —---------------------------- */
.bb-faq { border-top: 1px solid var(--rule); }
.bb-faq details { border-bottom: 1px solid var(--rule); }
.bb-faq summary {
  list-style: none; cursor: pointer; padding: 18px 40px 18px 0; position: relative;
  font-size: clamp(16px, 1.4vw, 18px); font-weight: 500; letter-spacing: -0.005em;
}
.bb-faq summary::-webkit-details-marker { display: none; }
.bb-faq summary::after {
  content: "+"; position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  color: var(--red-text); font-size: 18px; transition: transform .22s;
}
.bb-faq details[open] summary::after { content: "−"; }
.bb-faq summary:hover { color: var(--red-text); }
.bb-faq-a { margin: 0; padding: 0 40px 20px 0; color: var(--muted); max-width: 74ch; }

/* — case filter tabs —--------------------------------------------------- */
.bb-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: clamp(20px, 2.4vw, 32px); }
.bb-tab {
  border: 1px solid var(--rule); background: transparent; color: var(--muted);
  padding: 10px 15px; cursor: pointer;
  font-family: var(--mono); font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  transition: border-color .2s, color .2s, background-color .2s;
}
.bb-tab:hover { border-color: var(--muted-dim); color: var(--paper); }
.bb-tab[aria-selected="true"] { background: var(--red); border-color: var(--red); color: var(--teal); }
/* Filtered-out cards. Scoped to .bb-frame rather than to one page's card
   class: .bb-frame sets display:flex, which outranks the UA's [hidden] rule,
   so without this the attribute is set and the card stays on screen. That is
   what happened when /for-bedrifter got tabs — its cards are .bb-card, and
   this rule named .bb-case. Both are .bb-frame, so both are covered now. */
.bb-frame[hidden] { display: none; }

/* — video —-------------------------------------------------------------- */
.bb-video { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--ink-2); }

@media (max-width: 1100px) { .bb-segmenu { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 760px)  { .bb-segmenu { grid-template-columns: 1fr; } }

.bb-tab-n { color: var(--muted-dim); margin-left: 4px; }
.bb-tab[aria-selected="true"] .bb-tab-n { color: rgba(16,57,72,.78); }
.bb-tab:disabled { opacity: .35; cursor: not-allowed; }
.bb-tab:disabled:hover { border-color: var(--rule); color: var(--muted); }

/* ── spacing + logo-wall corrections ──────────────────────────────────── */

/* Two stacked bands add their paddings together — ~143px of dead space with
   nothing in it. Halve the second one's top edge so sections still breathe
   without a hole between them. */
.bb-band + .bb-band-tight,
.bb-band-tight + .bb-band-tight,
.bb-band-tight + .bb-band { padding-top: clamp(20px, 2.4vw, 34px); }

/* The client marks are square icon glyphs (24×24 viewBox), not wordmarks, so
   at 26px they read as stamps lost in their cells. Bigger mark, tighter cell,
   narrower columns — the row reads as one band rather than scattered dots. */
.bb-marks { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
.bb-mark { padding: 18px 14px; min-height: 72px; }
.bb-mark img { height: 30px; opacity: .5; transition: opacity .28s, transform .28s; }
.bb-mark:hover img { opacity: 1; transform: scale(1.06); }

/* The trailing "also worked with" line needs room to read as a caption. */
.bb-marks + .bb-note { margin-top: 18px; color: var(--muted-dim); line-height: 1.7; }

/* 12 marks over auto-fit gave 8+4. Fixed counts that divide 12 evenly:
   6×2 desktop, 4×3 tablet, 3×4 mobile. Same lesson as the mega-menu grid. */
.bb-marks { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 900px) { .bb-marks { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bb-marks { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* The band ABOVE contributes most of the gap (up to 104px). When it is
   followed by a tight band, pull its bottom edge in too — 138px of empty
   ground at 1920 becomes ~90px, which reads as a pause rather than a hole. */
.bb-band:has(+ .bb-band-tight) { padding-bottom: clamp(22px, 2.6vw, 42px); }

/* The nav grew with the new IA ("Bryllup og feiringer" is long) and no longer
   fits between logo and CTA until ~1100px — at 1024 it butted into the button
   and wrapped it onto two lines. Hold the burger until the nav genuinely fits. */
@media (max-width: 1100px) {
  :root { --header-h: 74px; }
  .bb-header-in { height: 74px; }
  .bb-nav { display: none; }
  .bb-burger { display: inline-flex; }
}

/* Per-page mark lists carry whatever number of brands that page's doc names —
   5, 8, 9, 10 — so a partial last row left the container's hairline
   background showing as an empty cell. Border each cell instead of the
   container and overlap the borders, so a short last row simply stops. */
.bb-marks-fit { background: none; border: 0; gap: 0; }
.bb-marks-fit .bb-mark { border: 1px solid var(--rule); margin-left: -1px; margin-top: -1px; }

/* Gallery columns match the image count (capped at 4), so a trailing empty
   cell never shows the grid's hairline background as a grey block. */
.bb-gal { grid-template-columns: repeat(var(--gal-cols, 4), minmax(0, 1fr)); }
@media (max-width: 900px) { .bb-gal { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .bb-gal { grid-template-columns: minmax(0, 1fr); } }

/* — photo grid —--------------------------------------------------------- */
/* Two rows of stills, full-bleed. Replaced a left-to-right marquee: the client
   found the motion at odds with the rest of the page, and two static rows show
   twice the work without asking anyone to wait for it to scroll past.

   Twelve tiles at every breakpoint's column count — 6, 4, then 2 — so the grid
   is always a complete rectangle. Left to auto-fit, a trailing empty cell shows
   this container's hairline colour as a large grey block. */
.bb-photogrid {
  display: grid; gap: 1px; background: var(--rule);
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
/* Six columns hold down to tablet — at 700px the tiles are still ~115px, which
   reads as a mosaic. Below that they would be thumbnails, so the grid narrows
   and grows taller instead: 4 across, then 2 on a phone. Both divide twelve. */
@media (max-width: 700px) { .bb-photogrid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bb-photogrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* A qualifier under the hero lead ("kan også tilpasses som…"). Narrower than
   the lead and set in the note colour, so it reads as a footnote to the pitch
   rather than a second, competing pitch. */
.bb-hero-note { max-width: 52ch; margin-top: 14px; }

/* Source line under a case video, centred on the player above it. */
.bb-video-credit { text-align: center; margin-top: 14px; }

/* — bryllup: package cards —--------------------------------------------- */
/* Three priced packages rather than the usual "ask us" tile, so the card
   carries a price and a spec list and has to stay readable at three across. */
/* Fixed at three, not auto-fit: these are meant to be compared, and auto-fit
   dropped to two columns and stranded the third package on a row of its own.
   Below 1000px they stack — one full-width card each, still comparable by
   scrolling, with no orphan. */
.bb-pakker { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1000px) { .bb-pakker { grid-template-columns: minmax(0, 1fr); } }
.bb-pakke-price {
  margin: 6px 0 14px; font-size: clamp(19px, 1.9vw, 24px);
  font-weight: 700; letter-spacing: -0.03em; color: var(--paper);
}
/* The feature list inside a card: the .bb-feats hairline grid is built for a
   full-width section and looks like a table in a 310px column, so here it is
   a plain bulleted list at body size. */
.bb-feats-plain {
  display: block; border: 0; margin: 16px 0 0; padding: 0; list-style: none;
}
.bb-feats-plain li {
  display: flex; align-items: baseline; gap: 10px;
  padding: 4px 0; border: 0;
  font-size: 14.5px; line-height: 1.5; color: var(--muted);
}
.bb-feats-plain li::before {
  content: ""; flex: none; width: 4px; height: 4px;
  background: var(--red-text); transform: translateY(-2px);
}
/* The "planlegger dere et bedriftsarrangement?" line above the hero. */
.bb-crossroad { padding-bottom: 0; }

/* — sample video —------------------------------------------------------- */
/* These clips are phone-shot 9:16, so the cap is on WIDTH — left to fill the
   shell a 1080x1920 clip is taller than any laptop screen. 420px is about the
   width of the phone it was filmed on, which is also how it will be watched.
   Centred rather than left-aligned: at this width a flush-left video reads as
   a floated thumbnail that failed to wrap. */
.bb-video-sample { display: flex; justify-content: center; }
.bb-video-sample video {
  width: min(420px, 100%);
  aspect-ratio: 9 / 16;
  display: block; background: var(--ink-2);
  border: 1px solid var(--rule);
  object-fit: cover;
}

/* Anchor targets for the hero's "Se … i bruk" button — clear the sticky header. */
#i-bruk,
#resultater { scroll-margin-top: calc(var(--header-h) + 16px); }

/* — overview card grid —------------------------------------------------- */
/* Capped at four across — auto-fit was putting five on a wide screen, which
   made the cards too narrow for their titles. Real gaps rather than the
   shared-background hairline trick, so each card reads as its own object;
   that means the border moves from the container onto the cards. */
.bb-cards {
  background: none; border: 0;
  gap: clamp(16px, 1.8vw, 28px);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
/* Any frame in this grid, not just .bb-card — the case cards use .bb-case. */
.bb-cards > .bb-frame { border: 1px solid var(--rule); }
@media (max-width: 1180px) { .bb-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .bb-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .bb-cards { grid-template-columns: minmax(0, 1fr); } }

/* — overview card —------------------------------------------------------ */
/* Category as a chip on the image rather than a section heading above the
   grid, so the whole set reads as one flat grid. Sits top-LEFT: .bb-frame-media
   already puts its counter top-right. */
.bb-tag {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  padding: 5px 9px;
  background: rgba(255,255,255,0.92);
  font-family: var(--mono); font-size: 9.5px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--teal);
}
/* .bb-frame-foot carries margin-top:auto, but it lives inside .bb-frame-body,
   which is a plain block — so the auto margin had nothing to push against and
   the "Les mer" rows sat at ragged heights. Making the body the flex column
   that grows is what actually aligns them across a row. */
.bb-card .bb-frame-body { display: flex; flex-direction: column; flex: 1 1 auto; }
.bb-card .bb-frame-copy { margin-top: 10px; }
.bb-card .bb-frame-foot { border-top: 1px solid var(--rule); margin-top: auto; padding-top: 16px; }
.bb-card:hover .bb-frame-foot .bb-eyebrow { color: var(--paper); }

/* A strapline that introduces the gallery directly below it. Sits closer to
   its gallery than a normal .bb-h2 would, so the two read as one unit. */
/* Caption sits in the same section as its gallery, so it needs the gap to the
   images below — not the full band padding that separated them before. */
.bb-gallery-lead { margin: 0 0 clamp(16px, 1.8vw, 26px); max-width: 46ch; }

/* Intro copy runs in two text columns under the heading rather than beside it,
   so the block ends flat instead of leaving a tall empty column. */
/* One column, with a measure so the lines do not run the full page width. */
.bb-intro-copy { max-width: 74ch; }
.bb-intro-copy .bb-body { margin: 0 0 14px; }
.bb-intro-copy .bb-body:last-child { margin-bottom: 0; }


/* — for-bedrifter page parts —------------------------------------------- */
/* Feature list. Boxing each item made it read like a spreadsheet, so this is
   a ruled checklist instead: one hairline per row, the red square from
   .bb-status as the marker, and the text at full paper weight so it reads as
   content rather than as labels in a table.
   Columns stretch to the row height, so a wrapping item keeps its rule
   aligned with its neighbour. */
.bb-feats {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 0 clamp(28px, 4vw, 72px);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  border-top: 1px solid var(--rule);
}
.bb-feats li {
  display: flex; align-items: baseline; gap: 14px;
  padding: 16px 2px;
  border-bottom: 1px solid var(--rule);
  font-size: 16px; line-height: 1.5; color: var(--paper);
}
.bb-feats li::before {
  content: ""; flex: none;
  width: 5px; height: 5px; background: var(--red-text);
  transform: translateY(-2px);
}
/* Grouped variant. The client writes these as themed sets, and the default
   row flow would deal them across the columns — group 1's first three items
   would land in row 1 and the sets would vanish. Filling by COLUMN keeps each
   set in its own column, which is how the client's own document reads.
   Below the width where three columns fit it drops straight to one: two
   columns would split a three-group list down the middle and break them
   again, and the items are short enough that one column reads fine. */
.bb-feats-cols {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--feat-rows, 4), auto);
}
@media (max-width: 1000px) {
  .bb-feats-cols {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-flow: row;
    grid-template-rows: none;
  }
}

/* A named client we have no logo file for. Set as a wordmark at the same
   weight as the inverted glyphs so the row still reads as one band. */
.bb-mark-text {
  font-size: 12px; font-weight: 500; line-height: 1.4; text-align: center;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--muted-dim); transition: color .28s;
}
.bb-mark-text:hover { color: var(--paper); }

/* A case with no photograph. Rather than borrow another event's picture, the
   card carries its own padding and leads with the client name, so it sits in
   the same grid as the media cards without looking like a broken one. */
.bb-case-plain .bb-frame-body { padding: 0; }
.bb-case-plain .bb-eyebrow { margin-bottom: 10px; }

/* "Løsning" / "Effekt" labels inside a case card. */
.bb-case-key {
  display: block; margin-bottom: 4px;
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-dim);
}
.bb-frame-body .bb-frame-copy + .bb-frame-copy { margin-top: 12px; }

/* The full Løsning + Effekt copy makes each case card about a screen tall, so
   they read as a wall of text. The card is a teaser and the full write-up is
   one tap away on its own /caser page — so shorten the image and cap each
   paragraph. The clamp counts the label as a line, hence 4 rather than 3.

   Keyed to 900, not to phone width: .bb-sheet-2 keeps two columns down to
   ~720px, so at 760 the cards are still 348px wide and just as cramped. Above
   900 the columns are wide enough to carry the full copy. */
@media (max-width: 900px) {
  .bb-case .bb-shot { aspect-ratio: 16 / 9; }
  .bb-case .bb-frame-copy {
    font-size: 14.5px; line-height: 1.5;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4;
    overflow: hidden;
  }
  .bb-case .bb-frame-foot { padding-top: 16px; }
}

/* The price sits where the "Se mer" eyebrow normally sits, so it needs to
   read as the loudest thing in the card foot, not as another label. */
.bb-price { font-size: 15.5px; font-weight: 500; color: var(--paper); }

/* — hero badge —--------------------------------------------------------- */
/* A solid block above the headline, so the positioning line reads as a stamp
   rather than as a caption.

   Teal on the accent TINT, not on the solid accent: the tint keeps the stamp
   quiet above a headline in the same teal, and the pairing is 11:1. --teal
   rather than --paper so the badge keeps its dark text inside a photo hero,
   where --paper is re-pointed to white. */
.bb-badge-row { margin: 0 0 clamp(20px, 2.6vw, 34px); }
.bb-badge {
  display: inline-flex; align-items: center;
  padding: 11px 18px;
  background: var(--red-soft); color: var(--teal);
  font-family: var(--mono); font-size: clamp(11px, 0.95vw, 13px); font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
}
/* "Est 2012" is supporting detail. The hierarchy comes from weight and the
   divider, not from fading the text. */
.bb-badge-est {
  margin-left: 14px; padding-left: 14px;
  border-left: 1px solid rgba(16,57,72,0.34);
  font-weight: 500;
  /* On a phone the long first phrase wraps; without this the date breaks too
     and reads as "EST / 2012" stacked in its own column. */
  white-space: nowrap;
}
@media (max-width: 560px) {
  .bb-badge { padding: 9px 14px; letter-spacing: 0.14em; }
  .bb-badge-est { margin-left: 10px; padding-left: 10px; }
}

/* — centred hero —------------------------------------------------------- */
/* .bb-status, .bb-actions and .bb-marks-row are all flex containers, so
   text-align alone does not move them — each needs its own main-axis centring. */
/* — showreel hero (homepage) —------------------------------------------- */
.bb-hero-video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The service clips are 9:16 phone footage, so a wide hero crops them hard —
   only a horizontal band of the frame survives. Bias that band upward, where
   the subject usually is, rather than taking the centre by default. Behind a
   scrim this reads as motion and texture, not as a clip you watch. */
.bb-hero .bb-hero-video { object-position: 50% 38%; }

/* The photo heroes darken the LEFT, because their copy is left-aligned. This
   hero is centred over moving footage, so the scrim is even across the full
   width instead: a flat wash plus a vertical pass.

   Sampled across the showreel (187k pixels, 13 timestamps), it contains
   pure-white frames — luminance 1.0. So the contrast floor is set by a white
   flash, not by how the reel usually looks, and the scrim has to survive that.
   At these values ~15% of the video reaches the eye behind the headline and
   ~13% behind the 11px proof line, which measures 4.7:1 and 5.2:1 against a
   white frame. Both clear AA; the small line is the one with least room, so
   lighten the flat wash below 0.58 and it is the first thing to fail. */
.bb-hero-home .bb-hero-bg::after {
  background:
    linear-gradient(180deg, rgba(8,32,41,0.82) 0%, rgba(8,32,41,0.62) 45%, rgba(8,32,41,0.89) 100%),
    rgba(8,32,41,0.58);
}
/* Lifting the footage itself is the safer half of making it visible. The
   contrast floor is set by the BRIGHTEST pixel, and the reel already contains
   pure white — brightness() clips there, so the worst case cannot get worse,
   while every mid-tone gets lighter and the picture actually reads. */
.bb-hero-home .bb-hero-video { filter: brightness(1.32) contrast(1.06); }
/* Motion behind text is a genuine accessibility problem for some people, and
   a video that cannot be paused is worse. Honour the OS setting by freezing
   it on the poster frame. */
@media (prefers-reduced-motion: reduce) {
  .bb-hero-video { display: none; }
  .bb-hero-home .bb-hero-bg {
    background: url("/img/site/showreel-poster.jpg") center / cover no-repeat;
  }
}

/* Fills the fold. The subtraction is header + its 1px rule + the 46px ticker,
   so the moving strip sits fully inside the first screen rather than starting
   one pixel below it — the ticker is part of the first impression.
   svh rather than vh: on mobile, vh is the tallest-chrome value, which would
   push the ticker off-screen on load.
   min-height, not height — the block still grows if the copy needs it. */
.bb-hero-center {
  display: flex; flex-direction: column; justify-content: center;
  min-height: calc(100vh - var(--header-h) - 1px - 46px);
  min-height: calc(100svh - var(--header-h) - 1px - 46px);
  /* Overrides .bb-band's 104px top and bottom. The block is already centred
     inside a full-height box, so that padding only fights the min-height —
     on a 1280x860 laptop it pushed the ticker 89px below the fold. */
  padding-block: clamp(20px, 2.2vw, 40px);
  text-align: center;
}
/* Tighter internal rhythm than the standard band spacing — every pixel here
   comes off the fold, and the block is visually held together by being
   centred rather than by generous gaps. */
.bb-hero-center .bb-badge-row { margin-bottom: clamp(16px, 2vw, 26px); }
/* Shared by the centred homepage hero and the photo heroes below. */
.bb-hero-proof { margin: clamp(26px, 3.2vw, 44px) 0 14px; }

/* Marks inside a photo hero. Left-aligned rather than spread: these lists run
   5–10 brands, and space-between across the full shell strands them at the
   edges. Slightly brighter than on flat ink, since they sit over a scrim. */
.bb-hero .bb-marks-row { justify-content: flex-start; }
.bb-hero .bb-marks-row .bb-mark img { opacity: .6; }
.bb-hero .bb-marks-row .bb-mark-text { color: var(--muted); }
.bb-hero-center .bb-status,
.bb-hero-center .bb-actions,
.bb-hero-center .bb-marks-row { justify-content: center; }
/* Extra air above the button row so it reads as its own step rather than
   crowding the logo line directly above it. */
.bb-hero-center .bb-actions { margin-top: clamp(36px, 4.8vw, 66px); }
/* Centred prose needs a measure, or the client list runs the full page width
   and the ragged edges stop reading as one centred block. */
.bb-hero-center .bb-note { margin-inline: auto; max-width: 68ch; }

/* — logo row (no boxes) —------------------------------------------------ */
/* The boxed grid read as a table. This is the same marks, set as one line of
   free-standing glyphs — no cells, no rules. Sized by height rather than by
   cell width so wordmarks (Dior, Samsung) and icon marks (Netflix, Puma) sit
   on a common baseline instead of each filling its own box.
   Wraps below ~700px: twelve marks cannot hold one line on a phone. */
.bb-marks-row {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 14px clamp(18px, 2vw, 30px);
}
/* No space-between. It only ever applied to the two index heroes — the
   homepage centres its row and the photo heroes set flex-start, both of which
   out-specify it — and there it stretched twelve small glyphs across the whole
   1240px shell, so the line read as scattered rather than as one proof strip.
   Left-aligned at a fixed gap keeps it a cluster the eye takes in at once. */
.bb-marks-row .bb-mark {
  background: none; border: 0; padding: 0; display: inline-flex; align-items: center;
  /* .bb-mark carries min-height:72px for the boxed grid; without this the row
     is 72px tall for a 22px glyph. */
  min-height: 0;
}
.bb-marks-row .bb-mark img {
  height: 22px; width: auto; max-width: none;
  filter: var(--mark-filter); opacity: .6;
  transition: opacity .28s;
}
.bb-marks-row .bb-mark:hover img { opacity: 1; transform: none; }
/* Wordmark for a client with no artwork, matched to the glyph weight. */
.bb-marks-row .bb-mark-text {
  font-size: 12px; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted-dim);
}

/* — compact marks —------------------------------------------------------ */
/* Same band, hero scale. In the hero the block sits in one half of .bb-split,
   so the 6-up cells would crush the glyphs — 4-up divides 12 evenly and keeps
   the stamp texture. Must stay after the .bb-marks rules above to win. */
.bb-marks-sm { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.bb-marks-sm .bb-mark { padding: 12px 8px; min-height: 54px; }
.bb-marks-sm .bb-mark img { height: 19px; }
/* At 900 the split stacks and the block gets the full shell back — 6-up again. */
@media (max-width: 900px) { .bb-marks-sm { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bb-marks-sm { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.bb-marks-sm + .bb-note { margin-top: 12px; font-size: 11.5px; }

/* — labels stay mono —--------------------------------------------------- */
/* Body and headings moved to DM Sans. The small wide-tracked caps — buttons,
   status lines, eyebrows, keys, the ticker — are the part of the old identity
   the client's reference keeps, and they used to get the mono face simply by
   inheriting it from <body>. Now that <body> is the sans, they ask for it by
   name. (.bb-nav, .bb-tab, .bb-tag, .bb-badge and the drawer rows already did.) */
.bb-btn, .bb-status, .bb-eyebrow, .bb-more,
.bb-frame::before, .bb-ticker-run span,
.bb-stat-key, .bb-spec-key, .bb-case-key, .bb-quote-by,
.bb-field label, .bb-label,
.bb-logos span, .bb-mark-text,
.bb-drawer-head, .bb-mega-cat, .bb-mega-colhead,
.bb-footer h4, .bb-footer-bar, .bb-social a { font-family: var(--mono); }


/* ---- Blocksy chrome, mapped onto the design system ---- */
.ct-header,.ct-footer{background-color:var(--ink);color:var(--paper);}
.ct-header{border-bottom:1px solid var(--rule);}
.ct-footer{border-top:1px solid var(--rule);color:var(--muted);}
.ct-header .site-title a{color:var(--paper);font-weight:700;letter-spacing:-0.03em;text-decoration:none;}
.ct-header .ct-menu-link{color:var(--muted);font-size:11.5px;font-weight:500;letter-spacing:0.16em;text-transform:uppercase;}
.ct-header .ct-menu-link:hover,.ct-header .current-menu-item>.ct-menu-link{color:var(--red-text);}
.ct-footer a{color:var(--muted);text-decoration:none;}.ct-footer a:hover{color:var(--red-text);}
/* Nothing in this system is rounded. */
.ct-header *,.ct-footer *,.entry-content *{border-radius:0;}


/* ---- Elementor + Blocksy integration ---- */
/* Everything above is the design system as built for the static site. The
   rules below only reconcile it with the two platforms now rendering it. */

/* Blocksy resolves a heading's font through --theme-font-family instead of
   inheritance, so headings ignored the family set on <body> and dropped to the
   system stack -- which re-wrapped card headings and shortened those sections.
   Feeding the variable fixes headings, Blocksy's own chrome and the block
   editor in one place. */
:root {
  --theme-font-stack-default: 'DM Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --theme-font-family: var(--theme-font-stack-default);
  --theme-headings-color: var(--paper);
  --theme-text-color: var(--muted);
  /* Validation only. The accent is a pale blue-grey now, which cannot say
     "something is wrong" and is too light to read as text; this is the rust
     from the client's own Shopify palette, 4.9:1 on white. */
  --alert: #bc5631;
}
/* A custom property that references another is resolved where it is DECLARED,
   so the two Blocksy colours above were fixed to teal at :root. Inside a photo
   hero the design re-points --paper and --muted to white -- restate Blocksy's
   copies there too, or a bare <h1> in a hero would stay teal on the photo. */
.bb-hero:has(.bb-hero-bg) {
  --theme-headings-color: var(--paper);
  --theme-text-color: var(--muted);
}

/* Every Elementor container is display:flex. These sections were block-level
   in the design and their inner layout assumes normal flow; as flex parents
   they moved the hero's contents up by a line. */
/* .bb-hero-in carries .bb-shell too, and this rule (0,2,0) was outranking the
   design's own .bb-hero-in (0,1,0) -- which is a flex column that pins the
   hero copy to the bottom of the frame. Forcing block left the content at
   the top with the rest of the hero empty beneath it. Exclude it here and
   restate its layout below. */
.e-con.bb-hero,
.e-con.bb-shell:not(.bb-hero-in):not(.bb-hero-center),
.e-con.bb-band,
.e-con.bb-band-tight { display: block; }

/* Mirrors .bb-hero-in in the design system above. */
.e-con.bb-hero-in {
  display: flex;
  --flex-direction: column;
  --justify-content: flex-end;
}


/* The single HTML widget should fill its container and add no spacing of its
   own -- the section's own padding is the only spacing in this design. */
/* No width/margin forcing on widgets: section containers are block so their
   children fill anyway, and forcing it wrapped the flex rows. */

/* Blocksy gives every form control a fixed height and its own 16px type. This
   design sets its own padding and type scale, so a 40px box left about 12px for
   a 24.65px line and the value was sliced in half -- worst on the selects,
   which draw their text at the top of the box rather than centring it.
   Sizing to content restores the static build's 49-53px controls. */
.bb-form input,
.bb-form select,
.bb-form textarea {
  font: inherit;
  height: auto;
  min-height: 0;
}
/* Restated after the reset above, which would otherwise drop it. */
.bb-form textarea { min-height: 132px; }

/* ---- Elementor widgets wearing design-system classes ----
   A widget's CSS class lands on its outer wrapper, never on the element
   Elementor renders inside it. Font properties inherit, so the wrapper can
   carry the type; these rules only stop the inner element asserting its own
   (Blocksy gives every h1-h6 a size) and remove the wrapper's spacing.

   Styling by context rather than by class matters here: a paragraph the client
   adds in the editor will not have .bb-body on it, and it should still look
   right. */
.elementor-widget-heading .elementor-heading-title {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  text-wrap: inherit;
  margin: 0;
}
/* Nothing here touches the text widget. Its paragraphs are the page's own
   markup, classes and all, so the design system already styles them --
   and a blanket margin/colour reset here silently overrode rules like
   .bb-cta-band p, which sets both. */

/* Elementor's default gap between widgets; this design spaces its own. */
.e-con > .elementor-widget:not(:last-child) { --kit-widget-spacing: 0px; }

/* .bb-head is a flex row, .bb-sheet the card grid, .bb-frame a cell. As
   containers they must keep their own display, not Elementor's flex. */
/* Elementor's containers default to --flex-direction: column. .bb-head is a
   row -- heading on the left, its link on the right -- so it stacked them.
   Set the variable rather than the property, so the rest of Elementor's
   container machinery stays consistent with it. */
.e-con.bb-head { display: flex; --flex-direction: row; }

/* The theme zeroes the bottom margin of the last child of a text block --
   sensible for prose it owns, but here the paragraphs are the page's own
   markup and two of them carry a deliberate bottom margin: .bb-status opens
   a section and spaces itself from the headline, .bb-badge-row does the same
   above a hero title. Each is alone in its widget, so it is always the last
   child. Values mirror .bb-status and .bb-badge-row in the design system
   above -- change them together. */
.elementor-widget-text-editor > p.bb-status:last-child { margin-block-end: clamp(22px, 3vw, 38px); }
.elementor-widget-text-editor > p.bb-badge-row:last-child { margin-block-end: clamp(20px, 2.6vw, 34px); }
.e-con.bb-sheet { display: grid; }
.e-con.bb-frame { display: flex; flex-direction: column; }

/* A classless container is a layout wrapper carried over from the original
   markup. It must size to its content the way the <div> it replaced did --
   Elementor makes containers full width, which pushed the 'Alle tjenester'
   link out of the heading row and onto a second line. */
.e-con.bb-head > .e-con { width: auto; }

/* Elementor caps every direct child of a container at max-width:100%, with a
   selector (.elementor.elementor .e-con > .elementor-widget) specific enough
   to outrank the design system. Exactly one design rule sets a width on
   something that is now a widget wrapper, so restate that one above the cap
   rather than lifting the cap wholesale and losing Elementor's guard. */
.elementor.elementor .bb-cta-band > .elementor-widget.bb-h2 { max-width: 20ch; }

/* An Image widget wraps its <img> in a div. Where the design sizes the image
   against its frame -- .bb-shot crops to an aspect ratio, .bb-hero-bg fills the
   hero, .bb-mark centres a small glyph -- that wrapper has to be transparent to
   the sizing, or the crop is lost and the photo renders at its natural size.
   display:contents removes the box while keeping the image. */
.bb-shot > .elementor-widget-image,
.bb-hero-bg > .elementor-widget-image,
.bb-mark > .elementor-widget-image,
.elementor-widget-image > .elementor-widget-container { display: contents; }

/* Elementor zeroes every widget's bottom margin with
   `.e-con .elementor-widget.elementor-widget` -- specificity (0,3,0), which
   outranks any design class sitting on a widget wrapper. Only one such class
   sets a bottom margin: .bb-gallery-lead, the line above a photo grid. Restate
   it at matching weight. If another heading class is ever given a margin, it
   will need the same treatment. Value mirrors .bb-gallery-lead above. */
.e-con .elementor-widget.elementor-widget.bb-gallery-lead {
  margin-block-end: clamp(16px, 1.8vw, 26px);
}

/* ---- Elementor container defaults vs the design ----
   Audited across all 114 pages by comparing every container that carries a
   bb-* class against a control element with the same classes rendered outside
   Elementor. These are the only deviations that came back.

   Elementor makes every container a flex column. Each of these is ordinary
   block flow in the design -- .bb-shot crops a photo, .bb-hero-bg is the
   absolutely positioned backdrop, .bb-specs is a bordered list, .bb-intro-copy
   is a measure-limited column of prose. */
.e-con.bb-shot,
.e-con.bb-hero-bg,
.e-con.bb-specs,
.e-con.bb-intro-copy,
.e-con.bb-split-narrow { display: block; }

/* .bb-frame-foot is a row: label on the left, arrow on the right. */
.e-con.bb-frame-foot { --flex-direction: row; }

/* Same max-width clash as .bb-cta-band .bb-h2: Elementor's cap on container
   children (0,4,0) outranks the design. Mirrors .bb-gallery-lead above. */
.elementor.elementor .e-con > .elementor-widget.bb-gallery-lead { max-width: 46ch; }

/* ---- cards, rails and the logo wall as containers ----
   Once these became containers so their photos could be media items, they need
   their own display back from Elementor's flex default, and the filter has to
   keep working on them. */
/* nowrap matters as much as the direction: the rail is ONE row that scrolls
   sideways, and Elementor's containers wrap by default. Wrapping folded the
   cards onto several rows, which made the rail tall enough to scroll
   vertically under the pointer and stopped the arrows having anything to
   scroll. */
.e-con.bb-rail       { display: flex; --flex-direction: row; --flex-wrap: nowrap; }
.e-con.bb-marks      { display: grid; }
.e-con.bb-marks-row  { display: flex; --flex-direction: row; }

/* A filtered-out card is hidden with the hidden attribute. .e-con.bb-frame
   (0,2,0) outranks the design's .bb-frame[hidden] (0,1,1), so without this the
   card would stay on screen when its tab is deselected. */
.e-con.bb-frame[hidden],
.e-con[hidden] { display: none; }

/* ---- second audit after the cards, rails and logos went in ---- */

/* The homepage hero centres its block in a full-height box. Same clash as
   .bb-hero-in: it carries .bb-shell, which the block rule above was winning.
   Mirrors .bb-hero-center in the design system. */
.e-con.bb-hero-center {
  display: flex;
  --flex-direction: column;
  --justify-content: center;
}

/* The card's text half is ordinary block flow, not a flex column. */
.e-con.bb-frame-body { display: block; }

/* A logo is now an image widget wearing .bb-mark, and Elementor's widget
   display was overriding the design's centring grid. */
.elementor-widget.bb-mark { display: grid; }

/* .bb-hero-bg is absolutely positioned against the hero. Elementor gives every
   widget position:relative, so the widget wrapper became the containing block
   instead of .bb-hero -- and because its only child is absolute, the wrapper
   collapsed to zero height and took the video with it. Taking the wrapper out
   of layout hands the hero back as the containing block. */
.elementor-widget:has(> .bb-hero-bg) { display: contents; }

/* ---- videos as media items ----
   Each video is an Elementor Video widget so the file can be swapped from the
   library. Elementor wraps the <video> in its own markup and the design's rules
   name the element directly, so re-point them at the inner <video>.

   The class the markup carried (.bb-hero-video) now sits on the widget wrapper.
   filter applies to the wrapper and passes through visually; object-fit and
   object-position have to reach the element itself. */
.bb-hero-bg > .elementor-widget-video,
.bb-hero-bg .elementor-widget-video .elementor-wrapper {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.bb-hero-bg .elementor-widget-video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.bb-hero .bb-hero-video video { object-position: 50% 38%; }

/* The sample player keeps its 9:16 frame and centred column. */
.bb-video-sample .elementor-widget-video,
.bb-video-sample .elementor-wrapper { width: min(420px, 100%); }
.bb-video-sample .elementor-widget-video video {
  width: 100%;
  aspect-ratio: 9 / 16;
  display: block;
  background: var(--ink-2);
  border: 1px solid var(--rule);
}
/* The 9:16 frame is set as the widget's own Aspect Ratio option, so it stays
   visible and adjustable in the editor. The hero backdrop is sized by the rules
   above instead, and ignores the ratio entirely. */
.bb-hero-bg .elementor-wrapper { aspect-ratio: auto; }

/* A card is an <a>. Blocksy recolours a link on hover, which turned the card's
   heading blue - the design keeps card text at inherit throughout. */
.bb-frame:hover,
.bb-frame:focus,
.bb-frame:hover h2,
.bb-frame:hover h3 { color: inherit; }


/* ---- Blocksy header and footer, dressed as the design ----
   The chrome is now the theme's, so it is editable in the Customizer. Blocksy
   paints its rows rather than the <header>, and does it from a palette variable
   at the same weight as a plain .ct-header rule -- so these target the rows. */
/* Blocksy paints the row with [data-header*="type-1"] .ct-header
   [data-row*="middle"] - three selectors deep. Leading with body clears it
   without resorting to !important. */
body[data-header] .ct-header [data-row],
body[data-header] .ct-header [data-row] > div,
body[data-footer] .ct-footer [data-row],
body[data-footer] .ct-footer [data-row] > div {
  background-color: var(--ink);
  background-image: none;
}
/* The mark carries the name; the design never sets it twice. */
.ct-header .site-title, .ct-header .site-description { display: none; }
.ct-header { border-bottom: 1px solid var(--rule); }
.ct-footer { border-top: 1px solid var(--rule); }

/* Navigation: the same wide-tracked caps the design uses. */
.ct-header .ct-menu-link {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.ct-header .ct-menu-link:hover,
.ct-header .current-menu-item > .ct-menu-link,
.ct-header .current-page-ancestor > .ct-menu-link { color: var(--red-text); }

/* Dropdown panels sit on the surface tone, not white. */
.ct-header .sub-menu {
  background-color: var(--ink-2);
  border: 1px solid var(--rule);
  box-shadow: none;
}
.ct-header .sub-menu .ct-menu-link { letter-spacing: 0.1em; }

/* Nothing in this system is rounded, and the logo keeps its own scale. */
.ct-header *, .ct-footer * { border-radius: 0; }
.ct-header .site-logo-container img { height: 32px; width: auto; }

/* Off-canvas panel for the small-screen menu. */
#offcanvas .ct-panel-inner,
.ct-panel.ct-header { background-color: var(--ink); }
#offcanvas .ct-menu-link { color: var(--paper); font-family: var(--mono); }

/* ---- Contact Form 7 markup, mapped onto the design ----
   Contact Form 7 wraps every control in its own spans, so the design's classes
   never land on the element that needs them. These re-point the rules at what
   CF7 actually renders. */

/* CF7's wrapper spans must not become layout boxes of their own. */
.bb-form .wpcf7-form-control-wrap { display: contents; }

/* The service pills. CF7 renders each as
   span.wpcf7-list-item > label > input + span.wpcf7-list-item-label,
   so the label is the pill. */
.bb-choices .wpcf7-checkbox { display: flex; flex-wrap: wrap; gap: 8px; }
.bb-choices .wpcf7-list-item { margin: 0; display: block; }
/* The pill is a <label> sitting inside .bb-field, so the field-label rules
   (uppercase, wide tracking, muted) were landing on it. A pill is sentence
   case in the paper tone, so those are undone here. */
.bb-choices .wpcf7-list-item label {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 16px;
  border: 1px solid var(--rule);
  cursor: pointer;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: normal;
  text-transform: none;
  color: var(--paper);
  transition: border-color .2s, color .2s;
}
.bb-choices .wpcf7-list-item label:hover { border-color: var(--muted-dim); }
.bb-choices .wpcf7-list-item input { accent-color: var(--red-text); margin: 0; flex: none; }
/* CF7 puts the visible text in its own span inside the label, so colour both.
   Led with .bb-form to outweigh whatever else reaches the label. */
.bb-form .bb-choices .wpcf7-list-item label.is-on,
.bb-form .bb-choices .wpcf7-list-item label.is-on .wpcf7-list-item-label {
  border-color: var(--red-text);
  color: var(--paper);
}
/* A chosen pill fills with the tint as well: on a white page a border change
   alone is a thin signal. Mirrors .bb-choice:has(input:checked) above. */
.bb-form .bb-choices .wpcf7-list-item label.is-on { background: var(--red-soft); }

/* On a narrow screen the pills go full width so they stack cleanly instead of
   leaving ragged gaps. */
@media (max-width: 560px) {
  .bb-choices .wpcf7-checkbox {
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;
    flex: 1 1 100%;
  }
  .bb-choices .wpcf7-list-item label { display: flex; width: 100%; }
}

/* Consent checkbox: same treatment, one row. */
.bb-consent .wpcf7-list-item { margin: 0; }
.bb-consent .wpcf7-list-item label {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--muted);
  line-height: 1.6;
  cursor: pointer;
}
.bb-consent .wpcf7-list-item input { accent-color: var(--red-text); margin-top: 3px; flex: none; }

/* ---- The response after submitting ----
   CF7 prints this OUTSIDE the .bb-form wrapper, as a sibling inside <form>, so
   selectors hung off .bb-form never reached it. Led with body so the state
   rules outweigh CF7's own .wpcf7 form.sent version regardless of which
   stylesheet the browser prints last.

   The default is a thin 2px line that is easy to miss. This is the
   confirmation someone waits for, so it gets the weight of a panel. */
.wpcf7 form .wpcf7-response-output {
  margin: 28px 0 0;
  padding: clamp(20px, 2.4vw, 30px);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--red-text);
  background: var(--ink-2);
  color: var(--paper);
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.6;
}
body .wpcf7 form.sent .wpcf7-response-output {
  border-color: var(--rule);
  border-left-color: var(--red-text);
  color: var(--paper);
  font-weight: 500;
}
/* A problem reads as a warning, not as success. */
body .wpcf7 form.invalid .wpcf7-response-output,
body .wpcf7 form.unaccepted .wpcf7-response-output,
body .wpcf7 form.spam .wpcf7-response-output,
body .wpcf7 form.failed .wpcf7-response-output {
  border-color: var(--rule);
  border-left-color: var(--muted-dim);
  color: var(--muted);
}
/* Per-field errors, in the alert tone so they are findable. */
.bb-form .wpcf7-not-valid-tip {
  color: var(--alert);
  font-size: 13px;
  margin-top: 6px;
}
.bb-form .wpcf7-not-valid { border-color: var(--alert); }

/* The chosen pill's outline. Set from the wrapper because the label's own
   border-color is overridden further down the cascade. */
.bb-form .bb-choices .wpcf7-list-item.is-on label {
  border-color: var(--red-text);
}


/* ---- required fields, and when to complain ----
   Contact Form 7 validates as you leave a field, so an untouched form scolded
   you for the address the moment you clicked a checkbox. Hold the inline
   messages until a submit has actually been attempted -- CF7 puts .invalid,
   .sent, .failed or .unaccepted on the form at that point, so before any of
   those exist there is nothing to report yet. Once the visitor has submitted,
   live validation is genuinely useful and comes back. */
.wpcf7 form:not(.invalid):not(.unaccepted):not(.failed):not(.sent) .wpcf7-not-valid-tip {
  display: none;
}
.wpcf7 form:not(.invalid):not(.unaccepted):not(.failed):not(.sent) .wpcf7-not-valid {
  border-color: var(--rule);
}

/* The asterisk marking a required field, and its legend. */
.bb-req { color: var(--alert); }
.bb-form .bb-req-legend { margin: 0 0 4px; }

/* The offending field's own outline. Led with body for the same reason as the
   pills: a plainer selector loses to the form styles further down. */
body .wpcf7 form.invalid .wpcf7-not-valid,
body .wpcf7 form.unaccepted .wpcf7-not-valid {
  border-color: var(--alert);
}


/* The confirmation that replaces the form once it has been sent. */
.bb-thanks {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--red-text);
  background: var(--ink-2);
  padding: clamp(26px, 3.4vw, 48px);
}
.bb-thanks:focus { outline: none; }
.bb-thanks .bb-h2 { margin-top: 10px; }
.bb-thanks .bb-body { margin-top: 14px; max-width: 54ch; }


/* [hidden] is only display:none at user-agent weight, so any explicit display
   beats it -- and .bb-form is a grid. Same trap as .bb-frame[hidden] on the
   filtered card grids. */
.bb-form[hidden],
.wpcf7-response-output[hidden] { display: none; }


/* ---- Eventadresse suggestions ----
   The list is positioned against the field, above everything else on the page,
   and wears the same surface and hairline as the rest of the form. */
.bb-lookup { position: relative; }
.bb-lookup-list {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 320px;
  overflow-y: auto;
  background: var(--ink);
  border: 1px solid var(--rule);
  border-top: 0;
  box-shadow: var(--panel-shadow);
}
.bb-lookup-list[hidden] { display: none; }
.bb-lookup-list li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 11px 15px;
  cursor: pointer;
  border-bottom: 1px solid var(--rule);
}
.bb-lookup-list li:last-child { border-bottom: 0; }
.bb-lookup-list li:hover,
.bb-lookup-list li.is-on { background: var(--red-soft); }
.bb-lookup-list li.is-on .bb-lookup-main { color: var(--red-text); }
.bb-lookup-main { font-size: 15px; color: var(--paper); }
.bb-lookup-sub {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-dim);
}

/* ---- light palette on WordPress (2026-10-06) ----
   The design system above is the static build's light stylesheet, unchanged.
   These are the places where WordPress itself needed telling. */

/* Blocksy recolours every link on hover with its own palette blue
   (a:hover, 0,1,1 -- which outranks the design's plain `a { color: inherit }`).
   currentColor in a colour declaration means "what I would have inherited",
   so links keep the colour the design gave them and only the design's own
   hover rules change it. Same for the focus ring, which Blocksy draws in its
   palette colour 1. Doubled :root so this wins whichever order the theme's
   generated stylesheet loads in. */
:root:root {
  --theme-link-hover-color: currentColor;
  --theme-palette-color-1: var(--red-text);
}

/* The homepage hero is plain white in the approved design. On the static
   build the showreel was removed from the markup. Here it is page content the
   client edits, so it is left in place in the editor and only switched off
   on the front end -- delete this block and the showreel hero comes back
   exactly as it was, as a dark panel. Values mirror :root above; change them
   together. */
.bb-hero.bb-hero-home:has(.bb-hero-bg) {
  --paper:     var(--teal);
  --muted:     rgba(16,57,72,0.74);
  --muted-dim: rgba(16,57,72,0.56);
  --rule:      rgba(16,57,72,0.16);
  --red-text:  #3f7683;
  --mark-filter: none;
  --theme-headings-color: var(--paper);
  --theme-text-color: var(--muted);
  background: var(--ink);
  color: var(--paper);
}
.bb-hero.bb-hero-home:has(.bb-hero-bg) .bb-lead { color: var(--muted); }
.bb-hero.bb-hero-home > .bb-hero-bg { display: none; }

/* Card counters. Elementor draws a background overlay with every container's
   ::before -- left:0, and a width and height of 100%. The design uses the same
   pseudo-element for the 01/02/03 counter and sets only top and right, so
   Elementor's left and size leaked through: the counter's box stretched across
   the whole card and the number landed in the top-LEFT corner, on the border.
   Handing those three back puts it top-right, as on the static build. */
.e-con.bb-frame::before { left: auto; width: auto; height: auto; }

/* A card that is still a raw HTML widget sits one level below the grid. The
   grid stretches the widget's wrapper to the row height, but not the card
   inside it, so a shorter card left the sheet's hairline colour showing
   beneath it as a grey strip -- barely visible on black, obvious on white.
   Making the wrapper a one-cell grid passes the stretch down to the card. */
.e-con.bb-sheet > .elementor-widget-html { display: grid; }

/* The form's pills and consent line are <label>s inside .bb-field, so they
   picked up the mono face the field labels ask for. They are sentence-case
   body text, like the rest of what CF7's rules above undo for them. */
.bb-choices .wpcf7-list-item label,
.bb-consent .wpcf7-list-item label { font-family: var(--sans); }

/* Blocksy's own header only appears where a page is not on the Canvas
   template -- today that is the 404 page. Its logo comes from the Customizer
   and is the white mark, which vanished on the white header. Swapping the
   picture here leaves the Customizer setting and the Media Library alone. */
.ct-header .site-logo-container img { content: url("/img/blitzbox-logo-teal.png"); }


/* ---- photo grids and case galleries: one picture, one tile (2026-10-07) ----
   Each picture used to sit inside its own cropping container (.bb-shot), and
   in a gallery that sat inside a .bb-frame as well. The crop hides anything
   that overflows it -- so when an editor duplicated a picture, or dropped a
   new Image widget next to one, the newcomer landed inside the same crop box
   and simply never showed.

   Here the wrappers step out of the layout (display: contents) and the Image
   widget itself becomes the tile. However a picture gets into the grid --
   duplicated, dropped straight into the grid, or dropped into an old wrapper
   -- it takes its own cell.

   Scoped to case galleries (.bb-gal) and the five-across grids
   (.bb-photogrid-5) ON PURPOSE. The older six-across grids on the service
   pages keep their wrappers: /tjenester/photobooth already has stray second
   pictures and empty Image widgets sitting hidden inside six of its tiles,
   and applying this there turned twelve tiles into sixteen with two blank
   ones. Widen the scope only after those pages have been tidied. */
.e-con.bb-photogrid-5 > .bb-shot,
.e-con.bb-gal > .bb-frame-media,
.e-con.bb-gal .bb-shot { display: contents; }

.e-con.bb-photogrid-5 .elementor-widget-image,
.e-con.bb-gal .elementor-widget-image {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--ink-2);
}
.e-con.bb-photogrid-5 .elementor-widget-image { aspect-ratio: 1 / 1; }
.e-con.bb-gal .elementor-widget-image { aspect-ratio: 4 / 3; }

/* Absolutely positioned rather than height:100%, so the crop holds even when
   the widget wraps its picture in a link or a caption figure. */
.e-con.bb-photogrid-5 .elementor-widget-image img,
.e-con.bb-gal .elementor-widget-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  display: block;
  transition: transform .7s cubic-bezier(.2,.7,.2,1);
}
/* The zoom on hover belongs to the one picture under the pointer. Left on the
   frame, two pictures sharing an old wrapper would both move. */
.e-con.bb-gal .bb-frame:hover .bb-shot img { transform: none; }
.e-con.bb-gal .elementor-widget-image:hover img { transform: scale(1.05); }

/* A gallery holds whatever number of pictures the page has. The sheet's usual
   trick -- a hairline-coloured container showing through 1px gaps -- paints
   every EMPTY cell as a grey block, which is what a fourth column did under
   three pictures. So the container goes clear and each tile draws its own
   hairline; outlines of neighbours meet inside the 1px gap and read as one.

   Up to four across, and auto-fit lets one, two or three pictures share the
   full width instead of leaving a hole. */
.e-con.bb-gal {
  background: none;
  border: 0;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(max(200px, calc((100% - 3px) / 4)), 1fr));
}
.e-con.bb-gal .elementor-widget-image { outline: 1px solid var(--rule); }
@media (max-width: 900px) { .e-con.bb-gal { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .e-con.bb-gal { grid-template-columns: minmax(0, 1fr); } }

/* Ten pictures, five across: the grid under the hero on the For bedrifter
   pages. Ten does not divide by the standard grid's four-across tablet step,
   so this one holds five until the tiles get small and then goes straight to
   two. The "Kolonner (bilderutenett)" field on the container still overrides
   it per device. */
.bb-photogrid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 700px) { .bb-photogrid-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The sample video. Elementor stretches the widget across the container, and
   the 420px player inside it then sat against the left edge -- centring the
   widget (which the container already asks for) moved nothing, because the
   widget was already full width. Centre the player inside it instead. */
.bb-video-sample .elementor-widget-video .elementor-wrapper { margin-inline: auto; }


/* ---- the October 2026 menu ----
   Nine services now that Photobooth abonnement has joined them, so the
   Tjenester panel is three across at every width: 3x3, where the four-across
   layout would leave one tile alone on a third row. */
.bb-mega-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* "Blitzbox Mini - bestill online" made the menu about 100px wider than the
   item it replaced, and below ~1160px it ran into the Send foresporsel button.
   Hold the burger until 1200px. chrome.js closes the open drawer at the same
   width (its matchMedia query) -- change the two together. */
@media (max-width: 1200px) {
  :root { --header-h: 74px; }
  .bb-header-in { height: 74px; }
  .bb-nav { display: none; }
  .bb-burger { display: inline-flex; }
}
/* The design system hides the drawer outright from 1101px up, with
   !important. Between there and the new breakpoint it has to be allowed back. */
@media (min-width: 1101px) and (max-width: 1200px) {
  .bb-drawer:not([hidden]) { display: block !important; }
}


/* ============================================================================
   9 October 2026
   ========================================================================== */

/* The menu is set in capitals. "MINI by BLITZBOX" is written with a small
   "by", so that word opts out. */
.bb-keepcase { text-transform: none; }

/* ---- sections built by hand in Elementor ----
   A section added straight from Elementor's panel is a plain container with
   none of this design's classes. Elementor gives it its own idea of an edge --
   10px, or 20px once a column is nested in it -- while every section built for
   the site starts at the shell's gutter. On one page that put headings at 10,
   20, 55 and 65px from the left.

   So a plain top-level container is treated as a shell: same width, same
   gutters, a modest band of space above and below. Columns nested inside one
   add no indent of their own; the gap between columns still separates them.

   Written with :where() so these stay weaker than a padding or width somebody
   sets on a container in Elementor on purpose. */
:where(.elementor) > .e-con:not([class*="bb-"]) {
  --width: min(var(--shell), 100%);
  --margin-left: auto;
  --margin-right: auto;
  --padding-left: var(--gutter);
  --padding-right: var(--gutter);
  --padding-top: clamp(20px, 2.4vw, 34px);
  --padding-bottom: clamp(20px, 2.4vw, 34px);
  margin-inline: auto;
}
:where(.e-con) .e-con:not([class*="bb-"]) {
  --padding-left: 0px;
  --padding-right: 0px;
}
/* A shell placed INSIDE a plain section would add the gutter a second time. */
.elementor > .e-con:not([class*="bb-"]) .bb-shell {
  width: 100%;
  padding-inline: 0;
}
/* A plain container whose only job is to wrap one finished band: the band
   brings its own space above and below, so the wrapper adds none. */
.elementor > .e-con:not([class*="bb-"]):has(> .bb-band:only-child, > .bb-band-tight:only-child, > .e-con-inner > .bb-band:only-child, > .e-con-inner > .bb-band-tight:only-child) {
  --padding-top: 0px;
  --padding-bottom: 0px;
}
/* A full-width container that holds nothing but one block of hand-written HTML
   is an edge-to-edge strip -- the homepage's running band of service names --
   and not a section to be lined up with the text. It keeps the whole width. */
.elementor > .e-con.e-con-full:not([class*="bb-"]):has(> .elementor-widget-html:only-child) {
  --width: 100%;
  --padding-left: 0px; --padding-right: 0px;
  --padding-top: 0px; --padding-bottom: 0px;
  margin-inline: 0;
}

/* ---- package cards (three across) ----
   Three offers side by side, each a photo, a small label, a name, one line of
   description, a checklist and a button. Built from ordinary Elementor widgets
   inside one container per card, so every word and picture stays editable.

   Made to be read as a set without scrolling: the photo's height is whatever
   the screen has left once the heading and the text are accounted for, so on a
   short laptop the photos shrink rather than the buttons falling off the
   bottom. The numbers: 470px is the section heading plus a card's text and
   button; 150-400px is the range the photo is allowed. Measured, not guessed --
   if the heading or the card text grows, re-measure it. */
.e-con.bb-plans {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 26px);
}
.e-con.bb-plan {
  display: flex;
  --flex-direction: column;
  --gap: 0px;
  --width: 100%;
  --padding-left: 0px; --padding-right: 0px; --padding-top: 0px; --padding-bottom: 0px;
  gap: 0;
  width: 100%;
  padding: 0 0 clamp(16px, 1.6vw, 22px);
  border: 1px solid var(--rule);
  background: var(--ink);
}
.bb-plan > .elementor-widget { padding-inline: clamp(16px, 1.6vw, 24px); }
.bb-plan > .elementor-widget-image {
  padding: 0;
  height: clamp(150px, calc(100svh - var(--header-h) - 470px), 400px);
  overflow: hidden;
  background: var(--ink-2);
}
.bb-plan > .elementor-widget-image img,
.bb-plan > .elementor-widget-image a { display: block; width: 100%; height: 100%; max-width: none; object-fit: cover; }
/* These are tall product shots in a wide, short frame. Favour the top of the
   picture, where the camera is, over the stand it sits on. */
.bb-plan > .elementor-widget-image img { object-position: 50% 18%; }
.bb-plan .bb-plan-eyebrow { margin-top: clamp(14px, 1.4vw, 20px); }
.bb-plan .bb-plan-eyebrow,
.bb-plan .bb-plan-eyebrow p {
  font-family: var(--mono); font-size: 10.5px; font-weight: 500; line-height: 1.4;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted-dim);
}
.bb-plan .bb-plan-eyebrow p { margin: 0; }
.bb-plan > .elementor-widget-heading { margin-top: 6px; }
.bb-plan .bb-plan-copy { margin-top: 6px; }
.bb-plan .bb-plan-copy p { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--muted); }
/* The checklist: Elementor's Icon List, redrawn as plain rows under a rule. */
.bb-plan > .elementor-widget-icon-list {
  position: relative;
  margin-top: 12px;
  padding-top: 8px;
}
.bb-plan > .elementor-widget-icon-list::before {
  content: ""; position: absolute; top: 0; height: 1px; background: var(--rule);
  left: clamp(16px, 1.6vw, 24px); right: clamp(16px, 1.6vw, 24px);
}
.bb-plan .elementor-icon-list-items { margin: 0; padding: 0; list-style: none; }
.bb-plan .elementor-icon-list-items .elementor-icon-list-item {
  display: flex; align-items: baseline; gap: 10px;
  margin: 0; padding: 4px 0;
  font-size: 14.5px; line-height: 1.45; color: var(--paper);
}
.bb-plan .elementor-icon-list-items .elementor-icon-list-item::after { content: none; }
.bb-plan .elementor-icon-list-icon { flex: none; display: inline-flex; width: 12px; transform: translateY(1px); }
.bb-plan .elementor-icon-list-icon svg,
.bb-plan .elementor-icon-list-icon i { width: 12px; height: 12px; font-size: 12px; fill: var(--red-text); color: var(--red-text); }
.bb-plan .elementor-icon-list-text { padding: 0; color: inherit; }
/* The button: Elementor's Button widget wearing .bb-btn. Pushed to the bottom
   of the card, so the three line up whatever the text above them runs to. */
.bb-plan > .elementor-widget-button { margin-top: auto; padding-top: 14px; }
.bb-plan .elementor-button {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 15px 18px;
  border: 1px solid transparent; border-radius: 0;
  background: var(--red); color: var(--on-red); fill: currentColor;
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; line-height: 1;
  letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none;
  transition: background-color .22s, color .22s, border-color .22s;
}
.bb-plan .elementor-button:hover,
.bb-plan .elementor-button:focus-visible { background: var(--red-deep); color: var(--on-red); }
/* The quieter one, for the offer that leaves for the web shop. */
.bb-plan .bb-plan-ghost .elementor-button { background: transparent; color: var(--paper); border-color: var(--red); }
.bb-plan .bb-plan-ghost .elementor-button:hover,
.bb-plan .bb-plan-ghost .elementor-button:focus-visible { background: transparent; color: var(--paper); border-color: var(--paper); }
@media (max-width: 900px) {
  .e-con.bb-plans { grid-template-columns: minmax(0, 1fr); }
  .bb-plan > .elementor-widget-image { height: auto; aspect-ratio: 16 / 10; }
}

/* ---- photo beside a short text ----
   For a section that has one picture and two or three sentences. Side by side
   at equal widths the picture swamped the words; here it takes the smaller
   share, is cropped to a calm 4:3, and the text is set large enough to hold
   its own without anyone having to write more of it. */
.e-con.bb-duo {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: center;
  gap: clamp(28px, 4.5vw, 80px);
}
.e-con.bb-duo > .e-con { --width: 100%; width: 100%; }
.bb-duo .bb-duo-text,
.bb-duo .bb-duo-text p {
  font-size: clamp(18px, 1.75vw, 25px);
  line-height: 1.5;
  letter-spacing: -0.008em;
  color: var(--paper);
}
.bb-duo .bb-duo-text { max-width: 30em; }
.bb-duo .bb-duo-text p { margin: 0; }
.bb-duo .bb-duo-text p + p { margin-top: 0.9em; }
@media (max-width: 900px) {
  .e-con.bb-duo { grid-template-columns: minmax(0, 1fr); }
}

/* ---- a video that fits the screen ----
   Elementor sizes a video to the full width of its container, so a square clip
   in a 1250px column is 1250px tall. With this class on the widget the player
   is as wide as it can be while its whole height, plus the heading above it,
   still fits one screen. --video-aspect-ratio is Elementor's own variable. */
.bb-video-fit .elementor-wrapper {
  width: min(100%, calc((100svh - var(--header-h) - 170px) * var(--video-aspect-ratio, 1.7777)));
  margin-inline: auto;
}

/* A cropping frame added by hand in Elementor comes with the container default
   of 10px padding, which shows as a pale border round the picture. The frames
   the site was built with all carry an explicit zero; this covers the rest. */
.e-con.bb-shot { --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px; }

/* The section that holds the package cards keeps little space above its
   heading and under its rule. A normal band has 70px of air on top, which is
   exactly what pushed the buttons off the bottom of a laptop screen. */
.e-con.bb-band:has(> .bb-plans) { padding-top: clamp(18px, 2vw, 28px); }
/* "Se losningene" in the hero jumps here. Land with the heading tucked right
   under the menu, so the whole set of cards is on screen in one go. */
/* Led with the id on purpose: the older #resultater rule further up sets a
   larger margin, and an id outranks any number of classes. */
#resultater.bb-band:has(> .bb-plans) { scroll-margin-top: calc(var(--header-h) - 14px); }
.e-con.bb-band:has(> .bb-plans) > .bb-head { padding-bottom: 14px; margin-bottom: clamp(16px, 1.6vw, 22px); }


/* ---- package cards: square photos (21 Oct 2026, Karen) ----
   On a computer the photo of each package card is square, so the whole
   photobooth shows instead of a wide crop. Phones keep the 16:10 frame set
   above. The cards get taller as a result; the section is no longer meant to
   fit one laptop screen. */
@media (min-width: 901px) {
  .bb-plan > .elementor-widget-image { height: auto; aspect-ratio: 1 / 1; }
  .bb-plan > .elementor-widget-image img { object-position: 50% 50%; }
}

/* ---- articles: a picture beside its words (julebord, sommerfest, bryllup) ----
   Karen builds every section of an article the same way: a heading, and under
   it a row of two columns, one holding a picture and the other a few short
   paragraphs. Laid out as built, the heading hung over both columns, the pair
   sat in a narrow strip on the left, and a rule and a wide gap closed every
   section.

   Here the row and its wrapper are set to display:contents, so the heading,
   the picture and the text all join one grid on the section: the picture
   takes two parts of five, the heading and the text share the other three,
   centred against the picture. Whichever column Karen put first decides the
   side, so the sections alternate as she laid them out, and a section she
   adds by duplicating one of hers is laid out the same way. On a phone they
   stack: picture, heading, text. Nothing in Elementor is moved; every word
   and picture is still edited where Karen left it.

   (:has() may not be nested inside :has(), so "text column first" is told by
   the widget inside it rather than by the absence of a picture.) */
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding-block: clamp(32px, 4.5vw, 64px);
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head,
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con { display: contents; }
/* The heading's box and the two columns: Elementor's widths and padding off. */
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .e-con:not(.bb-head),
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con > .e-con {
  --width: 100%; width: 100%; max-width: none;
  --padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con > .e-con:has(> .elementor-widget-image) {
  grid-row: 1;
  margin-bottom: clamp(18px, 2vw, 24px);
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .e-con:not(.bb-head) {
  grid-row: 2;
  margin-bottom: clamp(12px, 1.4vw, 20px);
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con > .e-con:not(:has(> .elementor-widget-image)) { grid-row: 3; }
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) .elementor-widget-image.elementor-widget-image {
  --container-widget-width: 100%;
  width: 100%;
  max-width: 100%;
}
/* Shown whole, never cropped: several are Karen's own collages (props, a grid
   of backdrops) that a crop cuts through. Capped at 500px tall so a square
   one doesn't tower over three short paragraphs; a narrower picture keeps to
   the outer edge, lined up with the page's margin. */
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) .elementor-widget-image img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 500px;
  object-fit: contain;
  object-position: left center;
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) .elementor-widget-text-editor {
  max-width: 38em;
  font-size: clamp(16px, 1.15vw, 18px);
  line-height: 1.65;
  color: var(--paper);
}
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) .elementor-widget-text-editor p { margin: 0 0 0.9em; }
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) .elementor-widget-text-editor p:last-child { margin-bottom: 0; }
@media (min-width: 768px) {
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    grid-template-rows: auto auto;
    column-gap: clamp(32px, 5vw, 96px);
  }
  /* Two auto rows under a picture that spans both share its spare height
     equally, so a heading at the foot of the first and the text at the head
     of the second meet in the middle: the pair is centred on the picture. */
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con > .e-con:has(> .elementor-widget-image) {
    grid-column: 1; grid-row: 1 / span 2; align-self: center; margin-bottom: 0;
  }
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .e-con:not(.bb-head) {
    grid-column: 2; grid-row: 1; align-self: end;
  }
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image) > .bb-head > .e-con > .e-con:not(:has(> .elementor-widget-image)) {
    grid-column: 2; grid-row: 2; align-self: start;
  }
  /* Text first in Karen's row: the picture goes to the right. */
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image):has(> .bb-head > .e-con > .e-con:first-child > .elementor-widget-text-editor) {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  }
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image):has(> .bb-head > .e-con > .e-con:first-child > .elementor-widget-text-editor) > .bb-head > .e-con > .e-con:has(> .elementor-widget-image) { grid-column: 2; }
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image):has(> .bb-head > .e-con > .e-con:first-child > .elementor-widget-text-editor) .elementor-widget-image img { object-position: right center; }
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image):has(> .bb-head > .e-con > .e-con:first-child > .elementor-widget-text-editor) > .e-con:not(.bb-head),
  :is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con.bb-band:has(> .bb-head > .e-con > .e-con > .elementor-widget-image):has(> .bb-head > .e-con > .e-con:first-child > .elementor-widget-text-editor) > .bb-head > .e-con > .e-con:not(:has(> .elementor-widget-image)) { grid-column: 1; }
}
/* Some sections sit inside extra one-child layout boxes, which shrink to
   their content; these make them fill the row like the rest. */
:is(.page-id-1812, .page-id-1813, .page-id-1814) .e-con > .e-con.e-con:only-child { flex: 1 1 100%; }

/* A heading built as a section of its own, right above a section of package
   cards (the articles, Bryllup). Stacked Elementor boxes left 88px between
   the heading and its cards and less above it than below; this closes it up
   to the cards the way .bb-head sits over them elsewhere, and gives the space
   to the section before it instead. */
.elementor > .e-con:not([class*="bb-"]):has(+ .e-con .bb-plans) { --padding-top: clamp(32px, 4.5vw, 64px); --padding-bottom: 0px; }
.elementor > .e-con:not([class*="bb-"]):has(+ .e-con .bb-plans) .e-con { --padding-top: 0px; --padding-bottom: 0px; }
.elementor > .e-con:not([class*="bb-"]):has(.bb-plans) { --padding-top: clamp(18px, 2vw, 28px); }

/* ---- Elementor's own Button widget ----
   A Button dropped in from Elementor's panel comes grey (#69727d) with round
   corners: Elementor's default, and no part of this site. Left unstyled it
   now looks like .bb-btn-solid. A colour picked for one button in Elementor
   still wins (that rule names the element and outranks this one), and the
   package cards keep their own version above. */
body .elementor-widget-button:not(.bb-plan > *) .elementor-button {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 15px 28px;
  border: 1px solid transparent; border-radius: 0;
  background: var(--red); color: var(--on-red); fill: currentColor;
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; line-height: 1;
  letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none;
  transition: background-color .22s, color .22s, border-color .22s;
}
body .elementor-widget-button:not(.bb-plan > *) .elementor-button:hover,
body .elementor-widget-button:not(.bb-plan > *) .elementor-button:focus-visible { background: var(--red-deep); color: var(--on-red); }
