/* ============================================================================
   aktiv-2026 preview SKIN — token override layer (first pass: re-skin, NOT
   re-layout). CONFIDENTIAL embargoed rebrand work.

   This file lives in public/ under an unguessable name so it can sit on prod
   hosting without ever being referenced when the gate is off (same embargo
   posture as the Bunny asset path). It is loaded by app/layout.tsx ONLY when
   NEXT_PUBLIC_BRAND_PREVIEW === "aktiv-2026", which also stamps
   data-brand="aktiv-2026" on <html>. Every rule below is scoped to
   html[data-brand="aktiv-2026"] so it is inert until that attribute is present.

   Specificity note: overrides are anchored on html[data-brand="aktiv-2026"]
   (0,1,1) so they beat both globals.css token homes — Tailwind v4 @theme's
   :root (0,1,0) and the legacy :root block (0,1,0) — regardless of the order
   in which the bundled globals.css and this <link> land in <head>.
   ============================================================================ */

/* ---- Aktiv 2026 typefaces (400 only — the new brand builds hierarchy by
        size, not weight). Served from the embargoed brand CDN path. --------- */
@font-face {
  font-family: "Aktiv Varighet";
  src: url("https://aktiv-signatur-cdn.b-cdn.net/brand/aktiv-2026-1ec0df52/fonts/AktivVarighet-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Aktiv Sans";
  src: url("https://aktiv-signatur-cdn.b-cdn.net/brand/aktiv-2026-1ec0df52/fonts/AktivSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Aktiv Sans Mono";
  src: url("https://aktiv-signatur-cdn.b-cdn.net/brand/aktiv-2026-1ec0df52/fonts/AktivSansMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Aktiv Fremover";
  src: url("https://aktiv-signatur-cdn.b-cdn.net/brand/aktiv-2026-1ec0df52/fonts/AktivFremover-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ============================================================================
   COLOR TOKENS — both namespaces overridden by ROLE.
   a26 palette: canvas #FAF5F0 · THE ONE TEXT INK #190C04 · legacy-namespace
   muted #875041 (the a26 layer's own muted grey is --a26-muted #6F655D, which
   is what every muted line the hub draws actually reads) · dark surfaces +
   accent #32140A · CTA fill #FF5F0F (dark text) · borders #DCD2C8 / #EBE1DC ·
   soft fill #FAE1D2.

   ONE TEXT INK (B&Y round 1, Sindre Annweiler, 2026-09-14): «Brunfargen til
   venstre burde være den mørkeste #190C04. Vi bruker aldri den som er brukt nå
   på tekst.» So every TEXT role in both namespaces below resolves to #190C04.
   The #32140A-class mid-brown survives only as a SURFACE (dark grounds, the
   strong accent) and as the shadow alpha; #4B281E is gone from text entirely.
   ============================================================================ */
html[data-brand="aktiv-2026"] {
  /* --- Tailwind v4 @theme namespace (utility classes: bg-aktiv-*, text-aktiv-*) --- */
  --color-aktiv-dark: #32140A;          /* SURFACE/accent role — kept: dark grounds, the strong accent, never a glyph */
  --color-aktiv-red: #FF5F0F;           /* brand red → CTA orange */
  --color-aktiv-black: #190C04;         /* TEXT role -> the one text ink */
  --color-aktiv-beige: #FAF5F0;         /* canvas */
  --color-aktiv-white: #FFFFFF;         /* white surfaces stay white */
  --color-aktiv-dark-grey: #190C04;     /* TEXT role -> the one text ink */
  --color-aktiv-satin: #DCD2C8;         /* warm border */
  --color-aktiv-greige: #875041;        /* muted text */
  --color-aktiv-pale: #EBE1DC;          /* light border / hover fill */
  --color-aktiv-dark-beige: #EBE1DC;    /* subtle border / pill fill */
  --color-aktiv-dusty-pink: #FAE1D2;    /* soft fill / accent bar */
  --color-aktiv-sage: #875041;          /* no green in a26 → muted brown */
  --color-aktiv-pine: #4B281E;          /* no green in a26 → secondary */
  --color-aktiv-grey: #DCD2C8;          /* neutral → warm border */
  --color-aktiv-deep: #190C04;          /* TEXT role -> the one text ink */
  --color-aktiv-warm-muted: #875041;    /* muted brown */
  --color-aktiv-warm-greige: #875041;   /* muted brown */
  --color-aktiv-tan: #EBE1DC;           /* soft warm surface */
  --color-aktiv-burgundy-shadow: #32140A33; /* brown shadow @ ~20% alpha — a SHADOW, not text; kept */

  /* --- Legacy :root namespace (used by delivery-page CSS) --- */
  --aktiv-dark: #32140A;                 /* SURFACE/accent role — kept (see --color-aktiv-dark) */
  --aktiv-red: #FF5F0F;
  --aktiv-black: #190C04;                /* TEXT role -> the one text ink */
  --aktiv-beige: #FAF5F0;
  --aktiv-white: #FFFFFF;
  --aktiv-dark-grey: #190C04;            /* TEXT role -> the one text ink */
  --aktiv-satin: #DCD2C8;
  --aktiv-greige: #875041;
  --aktiv-pale: #EBE1DC;
  --aktiv-dark-beige: #EBE1DC;
  --aktiv-dusty-pink: #FAE1D2;
  --aktiv-sage: #875041;
  --aktiv-pine: #4B281E;
  --aktiv-grey: #DCD2C8;
  --bg-card-warm: linear-gradient(180deg, #FFFFFF 0%, #FDF9F5 100%);

  /* --- Semantic tokens --- */
  --bg-page: #FAF5F0;
  --bg-card: #FFFFFF;
  --text-primary: #190C04;
  --text-secondary: #190C04;
  --text-muted: #875041;
  --accent: #875041;                    /* interactive muted-brown accent */
  --accent-cta: #FF5F0F;                /* CTA orange */
  --border: #DCD2C8;
  --border-subtle: #EBE1DC;

  /* --- Font-family variables (consumed by inline style={{fontFamily:'var(--font-arya)'}}
         and the composed --font-family-* tokens). Headings → Varighet, body → Sans. --- */
  --font-arya: "Aktiv Varighet";
  --font-roboto: "Aktiv Sans";
  --font-family-arya: "Aktiv Varighet", "Aktiv Sans", Georgia, serif;
  --font-family-roboto: "Aktiv Sans", system-ui, -apple-system, sans-serif;
}

/* ============================================================================
   FONT APPLICATION.
   globals.css and many components hard-code the literal families 'Arya' /
   'Roboto' (not the CSS vars), so overriding the vars alone is not enough.
   - Body copy → Aktiv Sans.
   - Heading roles (h1–h3, the .*-title classes, and ANY element whose inline
     style names Arya via [style*="Arya"]) → Aktiv Varighet, weight 400.
   - ANY element whose inline style names Roboto → Aktiv Sans.
   !important is required to beat inline style="fontFamily:…". Scoped to
   data-brand, so zero effect with the gate off.
   ============================================================================ */
html[data-brand="aktiv-2026"] body {
  font-family: "Aktiv Sans", system-ui, -apple-system, sans-serif;
}

html[data-brand="aktiv-2026"] h1,
html[data-brand="aktiv-2026"] h2,
html[data-brand="aktiv-2026"] h3,
html[data-brand="aktiv-2026"] .delivery-hero-title,
html[data-brand="aktiv-2026"] .share-fallback-title,
html[data-brand="aktiv-2026"] .cta-card-title,
html[data-brand="aktiv-2026"] .dashboard-card-title,
html[data-brand="aktiv-2026"] .btn-download,
html[data-brand="aktiv-2026"] [style*="Arya"] {
  font-family: "Aktiv Varighet", "Aktiv Sans", Georgia, serif !important;
  font-weight: 400 !important;
}

html[data-brand="aktiv-2026"] [style*="Roboto"] {
  font-family: "Aktiv Sans", system-ui, -apple-system, sans-serif !important;
}

/* ============================================================================
   CTA CONTRAST FIX — the new brand NEVER uses white text on the orange fill.
   .btn-download fills with var(--accent-cta) (now #FF5F0F) but sets its text
   to var(--aktiv-white); force dark brown text + a matching orange glow.
   ============================================================================ */
html[data-brand="aktiv-2026"] .btn-download {
  /* The one text ink on the orange — 6.29:1 (devices doc §3 --a26-cta-text). */
  color: #190C04 !important;
  box-shadow: 0 2px 8px rgba(255, 95, 15, 0.18);
}
html[data-brand="aktiv-2026"] .btn-download:hover {
  background: #E9540A;
  box-shadow: 0 6px 24px rgba(255, 95, 15, 0.28);
}

/* ============================================================================
   LINK AFFORDANCE on the routes this sheet reaches but does not design.

   `app/layout.tsx` links this sheet from the ROOT layout, so its token block
   re-skins EVERY route in the app, not only the delivery hub — that is the
   rebrand working as intended (a 2019-coloured /personvern on flip morning
   would be the bug). But the remap collapses roles: aktiv-2019 used
   `--aktiv-dark` as a burgundy ACCENT, and several pre-a26 screens spend it as
   their link colour via inline `style={{ color: 'var(--aktiv-dark)' }}`. In
   a26 `--aktiv-dark` is #32140A, the same ink as body copy, and those anchors
   carry no underline of their own — measured 2026-09-13 on /auth/confirm:
   both recovery links computed rgb(50,20,10), identical to `--text-primary`
   and to `body`, `text-decoration: none`. A link no longer distinguishable
   from the sentence around it is a WCAG 1.4.1 failure, and /auth/confirm is an
   account-recovery screen.

   The repair is an underline, not a colour: a26 has no red, so there is no
   accent to put back, and the matcher is the inline style itself — it cannot
   reach the a26 trees, which never set that variable inline on an anchor
   (verified: zero hits under components/boligpromo-a26 and components/
   portal-a26). Legacy source is untouched, so the aktiv-2019 render is
   untouched.

   Known and deliberately NOT repaired here: the same collapse turns the error
   and status paragraphs on /auth/confirm, /login and /login/code from burgundy
   into body ink. They stay legible and the brand has no error colour to
   substitute — that is a design decision for the a26 session, not a CSS patch.
   ============================================================================ */
html[data-brand="aktiv-2026"] a[style*="--aktiv-dark"] {
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

/* ============================================================================
   LOGO ASPECT FIX — the a26 wordmark is an SVG loaded into <img> boxes that
   were sized for the old lockup PNG. object-fit: contain lets it scale inside
   the existing width/height box without distortion (no markup change). Scoped
   to the a26 asset URL so it only bites when the new logo is actually rendered.
   ============================================================================ */
html[data-brand="aktiv-2026"] img[src*="/aktiv-2026-1ec0df52/logos/"] {
  object-fit: contain;
}


/* ============================================================================
   ============================================================================
   DELIVERY-HUB STRUCTURAL LAYER (2026-09-03, re-aligned 2026-09-04,
   unified into ONE device system 2026-09-05).

   Everything above this line is the July RE-SKIN (token overrides that repaint
   the existing aktiv-2019 markup). Everything below is the aktiv-2026 delivery
   hub's OWN layer.

   SOURCE OF TRUTH: the AGENCY's "Promopakke nytt design" boards on page C-0 of
   "Aktiv maler v2" — LTK-0 desktop (1440x6518) and LTL-0 mobile (428x5485),
   exported to docs/design/exports/delivery-hub/{LTK-0,LTL-0}/. Henrik's ruling
   2026-09-04: these boards, not the July GS6-0 board this hub was first built
   to, are what the hub follows. Grammar and rationale:
   docs/design/2026-08-21-a26-signatur-design-language.md. Motion:
   docs/reference/2026-07-10-hub-v2-motion-spec.md under the shared grammar of
   docs/reference/2026-09-04-a26-web-motion-pass.md.

   THE DEVICE RULES this file implements are written up, token by token, in
   docs/reference/2026-09-05-a26-web-devices.md — that document is what the
   primer, visning and solgt implementers adopt. If a value here and a value
   there disagree, this file is wrong.

   This file is the ONE home for a26 literals in this app: the components under
   components/boligpromo-a26/** carry class names and content only — no hex, no
   font name, no ratio. Everything visual resolves here, and every font-size,
   line-height, gap, radius and control dimension below is a TOKEN from the
   ladders at the top of the block — a rule that needs a value the ladder does
   not have is a rule that is wrong.

   THE BOARDS' LAYOUT GRAMMAR, in one paragraph. Both boards are a two-column
   rail: the section's eyebrow sits alone in a narrow left column at the page
   gutter, and everything else — headline, media, copy, controls — lives in a
   wide right column. Desktop: 32px gutters on a 1440 page, eyebrow column
   464 wide, content column 912 wide starting at x=496. Mobile: 20px gutters on
   a 428 page and the rail collapses, eyebrow stacked above content. Sections
   are separated by whitespace and 1px hairlines, never by rules or shadows.
   ============================================================================
   ============================================================================ */

html[data-brand="aktiv-2026"] {
  /* ---- Color -------------------------------------------------------------
     Measured off the two boards. Where a board value fails WCAG AA on the
     ground it actually sits on it is darkened one step and logged as a
     deviation in the build notes — nothing else is invented. */
  --a26-canvas: #FAF5F0;       /* board root fill, both boards */
  --a26-peach: #FAE3D3;        /* the agent-advice panel */
  --a26-white: #FFFFFF;        /* the two panels (composer mock, caption) */
  /* ONE TEXT INK. B&Y round 1 (2026-09-14) counted three text colours on an
     a26 surface and ruled that the #32140A-class mid-brown is never one of
     them. What is left on this page is exactly TWO text colours — this ink and
     the one muted grey below — plus the reversals on dark grounds. */
  --a26-text: #190C04;         /* THE text ink: every glyph that is not a reversal */
  --a26-ink: #32140A;          /* DARK SURFACES ONLY: the progress fill. Never a glyph */
  --a26-ink-chrome: #190C04;   /* board's chrome ink: rules, outlines, labels, marks (the same value as --a26-text) */
  --a26-media-ground: #000000; /* the video previews' black GROUND — a surface, not an ink */
  /* NOT A HUB INK ANY MORE. The hub layer stopped reading this on 2026-09-14
     (B&Y round 1 folded its four text uses into --a26-text and gave the video
     preview's black ground the surface token above). It stays DEFINED because
     app/layout.tsx links this file from the ROOT layout, which makes it the
     only definition site for every --a26-* token — and the agent-portal sheet
     reads var(--a26-ink-flat) 85 times and the kontor sheet 4 times, neither
     of them defining it. Deleting it here would blank 89 declarations on two
     surfaces this session is scoped out of. Folding those 89 into the one text
     ink is the PORTAL session's half of B&Y #1; when that lands, this line and
     its readers go together. */
  --a26-ink-flat: #000000;
  --a26-body: #190C04;         /* running body copy — was the #4B281E mid-brown */
  /* Mono meta / tertiary descriptions. The boards' own value for the step body
     is #7A6F66, which computes to 4.47:1 on the canvas — under AA for the
     20px/16px text it is used on. Darkened one step to #6F655D (5.25:1 on
     canvas, 5.68:1 on white, 4.66:1 on the peach panel). Deviation logged. */
  --a26-muted: #6F655D;
  --a26-eyebrow: #190C04;      /* the Fremover eyebrow label — was #4B281E, i.e. B&Y #1's «brunfargen til venstre» */
  --a26-hairline: #190C04;     /* the accordion's 1px separators (board) */
  --a26-hairline-soft: rgba(25, 12, 4, 0.25);
  --a26-cta: #FF5F0F;
  --a26-cta-hover: #ED550C;
  --a26-cta-text: #190C04;     /* the boards never put white on the orange */
  --a26-green: #6FFF4B;        /* the status dot — never a fill, never text */
  --a26-on-dark: #FAF5F0;      /* reversal color over the hero photo */
  --a26-wordmark-on-dark: #E9E2DD; /* the board's wordmark fill over the photo */
  --a26-playchip: #F0F0F0;     /* the video thumbnails' play disc */

  /* ONE HOVER LANGUAGE (Henrik, 2026-09-05, after the visning hub's contact
     pill): an outlined control fills with the SAME ink as its 1px stroke and
     its label goes to canvas, so the fill meets the stroke seamlessly; the
     filled orange control darkens one step; a plain text link keeps its ink
     and gains an underline; nothing else changes on hover. Press = scale 0.98
     on every control. Hover only under (hover: hover). The visning and solgt
     hubs already fill with #190C04 — the chrome ink, not the #32140A display
     ink — so that is the value here too. */
  --a26-hover-fill: var(--a26-ink-chrome);
  --a26-hover-text: var(--a26-canvas);
  --a26-press-scale: 0.98;

  /* Hero scrim. NEITHER board draws one — both sample photos are dark
     interiors. A real delivery's hero is whatever photo the property has, so
     reversal type over it needs a floor. Two layers: the vertical ramp
     protects the top bar and the bottom edge, the radial is the floor under
     the type stack in the middle of the frame. Measured 2026-09-05: worst
     pixel behind every hero line 5.3:1 or better on both samples. Deviation
     logged.

     NEUTRAL BLACK, NOT WARM BROWN (B&Y round 1, #2 + #7, 2026-09-14: «unngå et
     brunt filter da dette gir alt et litt retro-preg»). The alphas are the
     measured type floor and do not move; only the hue does. Black at the same
     alpha is DARKER than the warm inks it replaces (rgba(47,31,10) and
     rgba(25,12,4) both carry luminance above 0), so every reversal line's
     contrast can only rise — the 5.3:1 floor is a floor, not an equality. */
  --a26-hero-scrim:
    radial-gradient(
      ellipse 62% 48% at 50% 54%,
      rgba(0, 0, 0, 0.55) 0%,
      rgba(0, 0, 0, 0) 72%
    ),
    linear-gradient(
      180deg,
      rgba(0, 0, 0, 0.68) 0%,
      rgba(0, 0, 0, 0.58) 18%,
      rgba(0, 0, 0, 0.55) 100%
    );

  /* ---- Type: the faces --------------------------------------------------
     Weight 400 only, everywhere. Hierarchy is size + family + case. */
  --font-a26-display: "Aktiv Varighet", Georgia, serif;
  --font-a26-headline: "Aktiv Fremover", "Aktiv Sans", system-ui, sans-serif;
  --font-a26-body: "Aktiv Sans", system-ui, -apple-system, sans-serif;
  --font-a26-mono: "Aktiv Sans Mono", ui-monospace, monospace;

  /* ---- Type: THE LADDER ---------------------------------------------------
     Every font-size on the page is one of these roles, and no rule below
     writes a px size of its own. Mobile values here (LTL-0 measured, with the
     near-duplicates the mobile board carries — 26/28, 22/24, 10/10.5/11/12,
     14/16 — collapsed onto one step each); the >=1024 block restates the
     roles at LTK-0's values. The a26 web ladder of record (type coherence
     audit 2026-09-05 §2) is EIGHT rungs plus two fluid ones, shared by all
     four a26 web surfaces:

       rung      mobile   desktop   face      used for
       display   40/40    100/100   Varighet  the hero address (fluid between)
       figure    56/56    96/96     Varighet  live data numerals — sharehubs
                                              only, no user on this surface
       h1        32/36    56/62     Varighet  quote, locality, footer nav
       h2        28/32    32/37     Varighet  intro headlines, agent name
       h3        24/28    32/37     Varighet  accordion rows, bulk headline,
                                              "Promopakke for"
       lede      16/22    24/34     Sans      intro + bulk body
       body      16/22    17/26     Sans      advice body, caption, composer,
                                              accordion body, top-bar word
       ui        16/20    16/20     Sans      every control label, status,
                                              contact pair, role, footer links,
                                              the mobile top bar
       mono      12/15    12/15     Mono      spec lines, legal, hints
       eyebrow   12/16    16/21     Fremover  the rail eyebrow

     THE THREE FOLDS (Henrik's D5, 2026-09-05). The hub's own kicker (18),
     step (20 desktop) and label (14) rungs are gone: each was one increment
     away from a rung the ladder already carries, so "Promopakke for" reads at
     h3 on phones, the accordion copy and the top-bar word at body on desktop,
     and the top bar's word + status label at ui. Six sizes at 428, seven at
     1440.

     h1 is fluid on desktop (40 at 1024 to 56 at 1440) so the advice quote
     and the footer nav scale with the column they sit in rather than
     stepping; the display address is fluid across the whole range. Both are
     ONE rung each, whatever the viewport computes them to. */
  --a26-t-display: clamp(34px, calc(14.62px + 5.93vw), 100px);
  --a26-lh-display: 1;
  /* The live-data numeral rung: 56 at 428, 96 at 1440. NOTHING on the hub
     uses it — the visning sharehub's countdown digits and colon are its only
     users — but it is declared here because this file is the ONE source the
     other three a26 surfaces copy their ladder from, and a rung that lives in
     two places drifts. */
  --a26-t-figure: clamp(56px, calc(39.08px + 3.953vw), 96px);
  --a26-lh-figure: 1;
  /* h1 on phones. Desktop restates it as a clamp; see the >=1024 rule. */
  --a26-t-h1: 32px;
  --a26-lh-h1: 1.11;
  --a26-lh-nav: 1.34;                 /* the footer nav's looser h1 leading */
  --a26-t-h2: 28px;
  --a26-lh-h2: 32px;
  --a26-t-h3: 24px;
  --a26-lh-h3: 28px;
  --a26-t-lede: 16px;
  --a26-lh-lede: 22px;
  --a26-t-body: 16px;
  --a26-lh-body: 22px;
  --a26-t-ui: 16px;
  --a26-lh-ui: 20px;                  /* inside a control */
  --a26-lh-ui-text: 22px;             /* the same size set as a line of text */
  --a26-t-mono: 12px;
  --a26-lh-mono: 15px;
  --a26-lh-mono-text: 16px;           /* a helper line in the mono size */
  --a26-t-eyebrow: 12px;
  --a26-lh-eyebrow: 16px;
  --a26-track-display: 0.01em;        /* Varighet's board tracking */
  --a26-track-eyebrow: 0.04em;        /* the eyebrow device, all a26 surfaces */
  --a26-track-mono: 0.01em;

  /* ---- Space --------------------------------------------------------------
     One 4px-based ladder; every gap and padding below is one of these. The
     boards' own section anchors (gutters, the rail split, the accordion row
     head, card widths) are kept as measured and listed under Geometry. */
  --a26-s-1: 4px;
  --a26-s-2: 8px;
  --a26-s-3: 12px;
  --a26-s-4: 16px;
  --a26-s-5: 24px;
  --a26-s-6: 32px;
  --a26-s-7: 48px;
  --a26-s-8: 64px;
  --a26-s-9: 96px;

  /* ---- Controls -----------------------------------------------------------
     ONE button device (Henrik, 2026-09-05): height 48, padding 0 19, a 17px
     glyph always present, gap 8, label Sans 16/20, SQUARE corners. Two skins,
     the filled orange verb and the 1px-ink outline — identical geometry. The
     status pill is the same box, outlined in the reversal colour — and it is
     CHAMFERED: the agency board (LTK-0) draws the four-corner cut on "Klar
     til deling", which the 2026-09-05 ruling had reserved for the contact
     pair alone. Henrik, 2026-09-10: the board is right and we were not.
     TWO chamfered controls now, and only two — the joined contact pair (its
     notch + 4px cuts) and the status pill (the cuts, no notch). Every other
     corner on the page is square, buttons included. */
  --a26-control-h: 48px;
  --a26-control-pad: 19px;
  --a26-control-gap: 8px;
  --a26-icon: 17px;
  --a26-pair-h: 40px;                 /* the joined contact pair */
  --a26-pair-pad: 11px;               /* pair half: box edge / notch to label */
  --a26-chamfer: 5px;                 /* contact pair + status pill ONLY */
  --a26-notch: 3px;                   /* half-width of the pair's mid notch */
  --a26-dot: 8px;                     /* status dot, mobile; 13 on desktop */

  /* ---- Radii --------------------------------------------------------------
     Square everywhere except the two video previews (the design language's
     "one genuinely rounded element") and the discs that read as another app
     (play disc, composer avatar). */
  --a26-radius-media: 12px;
  --a26-radius-control: 0px;
  --a26-radius-card: 0px;
  --a26-hairline-w: 1px;

  /* ---- Motion -------------------------------------------------------------
     The six SHARED tokens first — identical name and value in every a26 web
     app (a26 web motion pass 2026-09-04 §1). Never redefine these locally and
     never write a literal easing or duration in a rule below. */
  --ease-a26: cubic-bezier(0.16, 1, 0.3, 1);        /* reveals + hero moves */
  --ease-a26-micro: cubic-bezier(0.4, 0, 0.2, 1);   /* hovers, presses, swaps */
  --dur-hero: 750ms;                                /* the signature move */
  --dur-reveal: 450ms;                              /* section entrances */
  --dur-micro: 200ms;                               /* hover / press / swap */
  --stagger-a26: 80ms;                              /* sibling stagger */

  /* Surface-local durations, so no rule below carries a bare `ms` literal. */
  --dur-a26-draw: 350ms;        /* section eyebrow hairline draw */
  --dur-a26-draw-load: 400ms;   /* page-load hairline + eyebrow text */
  --dur-a26-settle: 900ms;      /* hero photo slow settle */
  --dur-a26-pop: 250ms;         /* the ONE allowed pop — the ZIP pill */
  --dur-a26-chrome: 300ms;      /* card hover lift, chevron rotation */
  --dur-a26-tick: 420ms;        /* download-control icon tick */
  --dur-a26-progress: 120ms;    /* download progress fill */
  --dur-a26-reduced: 200ms;     /* the ONLY move left under reduced motion */
  --dur-a26-pulse: 2400ms;      /* the status dot's breath, one full cycle */

  /* Offsets INSIDE a compound reveal, added to the group's `--a26-delay`. */
  --delay-a26-eyebrow: 60ms;      /* eyebrow text after its hairline */
  --delay-a26-eyebrow-load: 80ms; /* same, page-load timing */
  --delay-a26-playchip: 350ms;    /* play chip lands at t=900 (550 + 350) */
  --delay-a26-zip-pop: 320ms;     /* the pill pops at the END of the band move */

  /* Page-load sequence. The page itself starts at opacity 1 — there is NO
     full-page fade. `--a26-load-scale` multiplies every `--a26-delay`; it is 1
     here and is only lowered inside the hero below 1024px, where the sequence
     was measurably holding the LCP element (Lighthouse 2026-09-04). */
  --a26-load-scale: 1;
  --delay-a26-load-title: 150ms;
  --delay-a26-load-sub: 400ms;

  /* ---- Format data --------------------------------------------------------
     The wide promo video is 4:3 on this brand (16:9 on aktiv-2019). The
     runtime authority for the value handed to React props is
     lib/brand-formats.ts (wideVideoAspect); this token is the CSS-side twin.
     Both must move together. */
  --a26-video-wide-aspect: 4 / 3;
  --a26-video-tall-aspect: 9 / 16;
  --a26-portrait-aspect: 4 / 5;

  /* ---- Geometry (the boards' own anchors) -------------------------------- */
  --a26-gutter: 20px;             /* LTL-0 page gutter */
  --a26-rail: 100%;               /* eyebrow rail collapses below 1024 */
  --a26-band: var(--a26-s-6);     /* section padding-block-start, mobile */
  --a26-band-end: var(--a26-s-6);
  /* The second band rhythm (Henrik's D4, 2026-09-05): a section that is a
     STAGE — a filled band or a stand-alone one, rather than a rail section
     parted from its neighbour by a hairline — breathes at 48 on phones and 96
     on desktop. On this surface the peach agent band is the only one; the
     sharehubs' hero row, countdown, gratulerer, delgleden and tilselger bands
     take the same pair, which is why it is a token and not a local value. */
  --a26-band-stage: var(--a26-s-7);
  --a26-measure: 620px;
  --a26-media-w: 583px;           /* the open row's film + the two panels */
  --a26-story-w: 189px;           /* the story preview */
  --a26-portrait-w: 123px;        /* LTL-0 portrait; 182 on LTK-0 */

  /* The graphics device (a26 graphics-delivery device spec 2026-09-05 §2.2,
     REV 1.3 of 2026-09-12). The stage is no longer a RESERVED box. Rev 1.2
     sized it to the Innlegg and letterboxed Story and Bredformat inside that
     one height, which meant the air around the graphic was equal only for the
     default format: a Story sat in two wide white gutters, a Bredformat in two
     deep white bands. Henrik, 2026-09-12: "let's have the white space equal on
     all sides of the graphic, so the max white space around the graphics is
     like the side of the portrait graphic. And let's try making that preview
     box adapt to the other formats when we click to the other formats."
     So the stage now FOLLOWS the format. Its width is the frame's content
     width at every format; the graphic fills that width less the padding; and
     the box height is whatever that width implies at the format's aspect,
     plus the padding back. The padding is the SAME on all four sides and is
     the only air there is — the Innlegg's side air, which is what Henrik named
     as the ceiling, is now the air on every side of every format.
     The mechanism is `aspect-ratio` on a CONTENT-BOX stage (see §.a26h-stage):
     the ratio lands on the content box, the padding is added outside it, and
     nothing has to be computed from a board width. That is what lets the
     geometry survive the 1024-1180 squeeze, where the two device columns
     shrink below 440 and a fixed height would have re-letterboxed.
     --a26-stage-h is therefore GONE. What the arithmetic lands, for the
     record (the frame board is 388 phone / 440 desktop, border-box, so the
     stage is 386 / 438 wide and the graphic 370 / 414):
       phone   8 pad:  Innlegg 370x462.5 -> 478.5 box
                       Story   370x657.8 -> 673.8
                       Bred    370x246.7 -> 262.7
       desktop 12 pad: Innlegg 414x517.5 -> 541.5 box
                       Story   414x736.0 -> 760.0
                       Bred    414x276.0 -> 300.0
     The Innlegg numbers are rev 1.2's 479 / 542 to within the rounding, which
     is the point: the default format did not move, the other two grew into
     their own air. THE HEIGHT CHANGE IS NOT ANIMATED (motion rule: no height
     tweens) — `aspect-ratio` is not in the stage's transition list, so the box
     snaps and the crossfade of spec §2.8 plays on top of it. */
  --a26-stage-pad: var(--a26-s-2);
  --a26-device-col: 440px;

  /* Minimum tap target. The 48px control clears it by itself; the 40px
     contact pair gets an invisible vertical extension to this. */
  --a26-tap: 44px;
}

@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] {
    /* The desktop ladder (LTK-0). h1 is fluid from 1024 to 1440 so the quote
       and the footer nav grow with the column: 40 at 1024, 56 at 1440.
       The slope is (56 - 40) / (1440 - 1024) = 16/416 = 1/26, written as a
       division rather than as a rounded 3.846vw + 0.6px pair: the rounded
       pair lands 55.98 at 1440, which is a NINTH size on the page, and the
       audit of 2026-09-05 counted it. Dividing by 26 lands 56.0000. */
    --a26-t-h1: clamp(40px, calc(40px + (100vw - 1024px) / 26), 56px);
    --a26-lh-nav: 1.25;
    --a26-t-h2: 32px;
    --a26-lh-h2: 37px;
    --a26-t-h3: 32px;
    --a26-lh-h3: 37px;
    --a26-t-lede: 24px;
    --a26-lh-lede: 34px;
    --a26-t-body: 17px;
    --a26-lh-body: 26px;
    --a26-t-eyebrow: 16px;
    --a26-lh-eyebrow: 21px;
    --a26-dot: 13px;

    --a26-gutter: 32px;
    /* LTK-0: 32px gutters on 1440 leave 1376; the eyebrow column is 464 wide
       (x=32..496) and the content column 912 (x=496..1408). 464/1376. */
    --a26-rail: 33.72%;
    /* The rail eyebrow's optical cap-top is pinned 2px above the adjacent
       content column's first-line cap-top (2026-09-15 alignment pass). The
       two content families that sit beside a rail eyebrow put their own first
       line at a DIFFERENT structural offset — the accordion row head
       (a26h-step-head) carries its own 16px padding-block that the eyebrow
       column has no equivalent of, while an intro block's h2 (a26h-intro) has
       none — so one fixed rail-label padding-top cannot hit 2px for both.
       These two trims replace that single value, keyed on the RUNG the first
       content line is set on (h3 for the accordion rows, h2 for intro
       blocks), never on which section it is — see .a26h-rail-label below and
       its :has() overrides. Measured with a Range+canvas cap-top probe
       (build notes appendix, 2026-09-15): h3 wants 16px, h2 wants 6.5px. */
    --a26-ink-trim-h3: 16px;
    --a26-ink-trim-h2: 6.5px;
    /* The footer's three sibling columns (mark / nav / secondary links) sit
       in one grid row and must share one visual top. The monogram SVG's own
       box top IS its visual top (no font leading); the nav rung (h1 size,
       the footer's own loose 1.25 leading) and the ui rung both carry a much
       bigger half-leading gap above their cap line, so each needs pulling up
       by its own measured amount — again keyed on the rung, not the column. */
    --a26-ink-trim-nav: -17px;
    --a26-ink-trim-ui: -8.5px;
    --a26-band: var(--a26-s-5);
    --a26-band-end: var(--a26-s-7);
    --a26-band-stage: var(--a26-s-9);
    --a26-portrait-w: 182px;
    --a26-stage-pad: var(--a26-s-3);
  }
}

/* ============================================================================
   HUB SHELL
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h {
  background-color: var(--a26-canvas);
  color: var(--a26-text);
  font-family: var(--font-a26-body);
  /* All four Aktiv faces ship at weight 400 only. Without this, any element a
     UA defaults to bold (an <h2>, a <strong>) gets a SYNTHESISED bold — a
     smeared weight the brand does not own. Belt and braces with the explicit
     `font-weight: 400` the headings already carry. */
  font-synthesis: none;
  font-weight: 400;
  margin-inline: auto;
  max-width: 1440px;
  position: relative;
  width: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
html[data-brand="aktiv-2026"] .a26h :where(h1, h2, h3, h4, p) {
  margin: 0;
}
html[data-brand="aktiv-2026"] .a26h-stack {
  display: flex;
  flex-direction: column;
}

/* ---- The rail: eyebrow left, everything else right ----------------------- */
html[data-brand="aktiv-2026"] .a26h-rail {
  display: grid;
  grid-template-columns: var(--a26-rail);
  padding-inline: var(--a26-gutter);
  row-gap: var(--a26-s-5);
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-rail {
    column-gap: 0;
    grid-template-columns: var(--a26-rail) minmax(0, 1fr);
    row-gap: 0;
  }
}
html[data-brand="aktiv-2026"] .a26h-rail-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
/* The eyebrow is optically aligned with the first line of the content column:
   on the boards it sits 2px above the headline's cap line, not on its
   baseline. Default trim is the accordion's (h3 rung: A26ShareSteps' step
   titles) — it is what a bare Rail with no known content shape gets. A rail
   whose body opens with an intro block's h2 (IntroBlock: "Grafikk for
   visning", "Nøkkelinfo", "Alle filer") overrides it via :has(), because that
   content sits at a different structural offset (see --a26-ink-trim-h2/h3
   above). Keyed on the CONTENT RUNG, never on the section — a third rung
   sitting beside a rail eyebrow needs a third trim token here, not a class
   name for its section. */
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-rail-label {
    padding-top: var(--a26-ink-trim-h3);
  }
  html[data-brand="aktiv-2026"] .a26h-rail:has(.a26h-intro) .a26h-rail-label {
    padding-top: var(--a26-ink-trim-h2);
  }
}

/* ============================================================================
   TYPE ROLES — one class per rung of the ladder.
   The re-skin block above forces Varighet on every h1/h2/h3 with !important,
   so the roles that are deliberately NOT Varighet have to say so at the same
   strength.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-display {
  color: var(--a26-on-dark);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-display);
  font-weight: 400 !important;
  line-height: var(--a26-lh-display);
  text-transform: uppercase;
  text-wrap: balance;
}
html[data-brand="aktiv-2026"] .a26h-h1 {
  color: var(--a26-text);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h1);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h1);
}
html[data-brand="aktiv-2026"] .a26h-h2 {
  color: var(--a26-text);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h2);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h2);
}
html[data-brand="aktiv-2026"] .a26h-h3 {
  color: var(--a26-ink-chrome);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h3);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h3);
}
/* Running copy — the body role by default, the lede and step roles by
   modifier. Each is one rung. */
html[data-brand="aktiv-2026"] .a26h-body {
  color: var(--a26-body);
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-body);
  font-weight: 400 !important;
  line-height: var(--a26-lh-body);
  max-width: var(--a26-measure);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-body {
    max-width: 760px;
  }
}
html[data-brand="aktiv-2026"] .a26h-body--lede {
  color: var(--a26-text);
  font-size: var(--a26-t-lede);
  line-height: var(--a26-lh-lede);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-body--lede {
    max-width: 940px;
  }
}
/* The accordion's step copy, the one place the boards use a lighter ink. It
   carried its own rung (16/22 phones, 20/28 desktop) until D5 folded the
   desktop 20 onto body 17 — a single increment, and the ink is what separates
   this copy from the lede beside it, not the size. Only the ink and the
   measure are left here. */
html[data-brand="aktiv-2026"] .a26h-body--step {
  color: var(--a26-muted);
  max-width: 915px;
}
/* The UI size set as a line of text: the agent's role, the footer's
   secondary links, the composer's name. */
html[data-brand="aktiv-2026"] .a26h-ui {
  color: var(--a26-ink-chrome);
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  line-height: var(--a26-lh-ui-text);
}
/* Mono spec lines — uppercase, 0.01em. The boards draw them plain black; B&Y
   round 1 replaces that third ink with the one text ink. */
html[data-brand="aktiv-2026"] .a26h-mono {
  color: var(--a26-text);
  font-family: var(--font-a26-mono) !important;
  font-size: var(--a26-t-mono);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-mono);
  line-height: var(--a26-lh-mono);
  text-transform: uppercase;
}
html[data-brand="aktiv-2026"] .a26h-mono--muted {
  color: var(--a26-muted);
}
/* A helper line under a control ("Velg Lagre video"): the mono size in the
   body face, muted. */
html[data-brand="aktiv-2026"] .a26h-hint {
  color: var(--a26-muted);
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-mono);
  line-height: var(--a26-lh-mono-text);
}

/* The eyebrow — Fremover, uppercase, 0.04em. It is the only
   Fremover on either board. Case and tracking are the eyebrow DEVICE, not this
   surface's taste: every board sets the rail label in caps and the sibling a26
   surfaces track it at 0.04em; source copy stays sentence case. */
html[data-brand="aktiv-2026"] .a26h-eyebrow {
  align-items: center;
  display: flex;
  gap: 0;
}
/* NO font-stretch HERE, and that is deliberate. The rule used to ask for
   `expanded`, but the Fremover @font-face at the top of this file declares one
   static Regular with no font-stretch descriptor, so the request matched the
   same face it would have matched anyway and CSS never synthesises width.
   Measured 2026-09-05 on the gate-on page: the eyebrow string sets to the
   same 220.453px at expanded, normal and condensed. The declaration was
   removed rather than left as a value that reads as if it does something.
   If a genuinely wider Fremover ever ships, it needs BOTH a second @font-face
   with a `font-stretch: 125%` descriptor and the property back here — one
   without the other is this same no-op. */
html[data-brand="aktiv-2026"] .a26h-mono--eyebrow {
  color: var(--a26-eyebrow);
  font-family: var(--font-a26-headline) !important;
  font-size: var(--a26-t-eyebrow);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-eyebrow);
  line-height: var(--a26-lh-eyebrow);
  text-transform: uppercase;
}
/* Neither board draws a rule beside the eyebrow — the label stands alone in
   its column. The element is kept (it is what the page-load and section
   entrances DRAW, motion spec §2) at zero width, so the reveal still has its
   target and nothing paints. */
html[data-brand="aktiv-2026"] .a26h-eyebrow-rule {
  background-color: var(--a26-eyebrow);
  flex-shrink: 0;
  height: var(--a26-hairline-w);
  width: 0;
}

/* ============================================================================
   CONTROLS — the one button device, in two skins.

   Geometry from the top of the file: h48, padding 0 19, glyph 17, gap 8,
   label ui 16/20, square. The glyph is ALWAYS present — every control on the
   page renders one (download, copy, share, tick, spinner) — so the
   left-aligned box never shows an empty slot. Orange is a VERB, and the verb
   is "Del": every control that says Del is orange, plus the ZIP (Henrik
   2026-09-06; graphics device spec §6.2 — the one-orange-per-device budget
   of §2.5 is withdrawn). Last ned / Kopier teksten are the outline.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-pill {
  align-items: center;
  align-self: flex-start;
  background-color: transparent;
  border: var(--a26-hairline-w) solid transparent;
  border-radius: var(--a26-radius-control);
  color: var(--a26-ink-chrome);
  cursor: pointer;
  display: inline-flex;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  gap: var(--a26-control-gap);
  line-height: var(--a26-lh-ui);
  min-height: var(--a26-control-h);
  padding-block: 0;
  padding-inline: var(--a26-control-pad);
  position: relative;
  text-align: left;
  text-decoration: none;
  transition:
    background-color var(--dur-micro) var(--ease-a26-micro),
    border-color var(--dur-micro) var(--ease-a26-micro),
    color var(--dur-micro) var(--ease-a26-micro),
    transform var(--dur-micro) var(--ease-a26-micro);
}
html[data-brand="aktiv-2026"] .a26h-pill svg {
  flex-shrink: 0;
  height: var(--a26-icon);
  width: var(--a26-icon);
}
html[data-brand="aktiv-2026"] .a26h-pill--cta {
  background-color: var(--a26-cta);
  border-color: var(--a26-cta);
  color: var(--a26-cta-text);
}
html[data-brand="aktiv-2026"] .a26h-pill--quiet {
  border-color: var(--a26-ink-chrome);
}

/* A control whose label swaps in place ("Kopier teksten" -> "Kopiert!")
   reserves the wider of its two labels so the box never changes width on
   click: both are stacked in one grid cell, the ghost invisible. */
html[data-brand="aktiv-2026"] .a26h-pill-label {
  display: inline-grid;
  white-space: nowrap;
}
html[data-brand="aktiv-2026"] .a26h-pill-label > span {
  grid-area: 1 / 1;
}
html[data-brand="aktiv-2026"] .a26h-pill-ghost {
  visibility: hidden;
}

/* --- Hover + press: the one language ------------------------------------- */
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-pill--cta:hover {
    background-color: var(--a26-cta-hover);
    border-color: var(--a26-cta-hover);
  }
  html[data-brand="aktiv-2026"] .a26h-pill--quiet:hover {
    background-color: var(--a26-hover-fill);
    border-color: var(--a26-hover-fill);
    color: var(--a26-hover-text);
  }
}
html[data-brand="aktiv-2026"] .a26h-pill:active {
  transform: scale(var(--a26-press-scale));
}

/* Copy confirmation: the outline fills for the "Kopiert!" window the same way
   its hover does — one language for "this control did something". */
html[data-brand="aktiv-2026"] .a26h-pill--quiet[data-a26-state="copied"] {
  background-color: var(--a26-hover-fill);
  border-color: var(--a26-hover-fill);
  color: var(--a26-hover-text);
}
/* Copy FAILURE. The outline is unchanged — a failed copy is not an error
   surface, it is an instruction ("marker teksten") — and the only new mark is
   a small square in the CTA colour, the design language's attention token. It
   is a state on a control, never a verb, so it does not spend an orange
   moment. CopyCaptionPill holds the window. */
html[data-brand="aktiv-2026"] .a26h-pill[data-a26-state="failed"] .a26h-pill-dot {
  background-color: var(--a26-cta);
  display: block;
  flex-shrink: 0;
  height: var(--a26-s-2);
  width: var(--a26-s-2);
}

/* Download confirmation without a spinner: the icon ticks down and springs
   back. Instant saves get no progress line, so this is the only feedback. */
@keyframes a26h-tick {
  0% { transform: translateY(0); }
  38% { transform: translateY(3px); }
  100% { transform: translateY(0); }
}
html[data-brand="aktiv-2026"] .a26h-pill[data-a26-state="ticked"] svg {
  animation: a26h-tick var(--dur-a26-tick) var(--ease-a26-micro);
}
html[data-brand="aktiv-2026"] .a26h-pill[aria-disabled="true"] {
  cursor: default;
  opacity: 0.4;
}
html[data-brand="aktiv-2026"] .a26h-pill:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: 2px;
}
html[data-brand="aktiv-2026"] .a26h-progress {
  background-color: var(--a26-hairline-soft);
  height: 2px;
  overflow: hidden;
  width: 100%;
}
/* The fill is a full-width bar scaled on X, not an animated width: `width` is
   a layout property and the motion rules allow transform + opacity only. */
html[data-brand="aktiv-2026"] .a26h-progress > span {
  background-color: var(--a26-ink);
  display: block;
  height: 100%;
  transform-origin: left center;
  transition: transform var(--dur-a26-progress) linear;
  width: 100%;
}

/* ============================================================================
   01 + 02 + 03 — HERO PHOTO, TOP BAR, HERO TEXT
   (LTK-0 M0C-0 / MVG-0 / M37-0 · LTL-0 MBQ-0 / MIQ-0)

   One full-bleed frame carrying the PROPERTY'S HERO PHOTO, with the top bar
   and the centred address stacked over it in reversal type. LTK-0 draws it
   1440x899, LTL-0 428x548.
   ============================================================================ */
/* PAINT ORDER, and it is load-bearing. The photo carries the reveal's settle
   transform, and a transformed element creates a stacking context that paints
   in the positioned layer — ABOVE a plain, unpositioned sibling. So the scrim
   below was never composited over the photo at all (measured 2026-09-05).
   The hero is made an explicit stacking context here and its three layers are
   given explicit levels: photo 0, scrim 1, type 2. `z-index: 0` also keeps the
   whole frame below the top bar (z-index 2 in .a26h), which is a sibling of
   <main>, not a child of this section. */
html[data-brand="aktiv-2026"] .a26h-hero {
  aspect-ratio: 428 / 548;
  display: grid;
  z-index: 0;
  /* ONE definite row and column, not `auto`: the frame's height comes from its
     aspect ratio, and a `100%` height on a child only resolves against a grid
     area that is itself definite. */
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  overflow: hidden;
  position: relative;
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-hero {
    aspect-ratio: 1440 / 899;
  }
}
html[data-brand="aktiv-2026"] .a26h-hero-photo {
  display: block;
  grid-area: 1 / 1;
  height: 100%;
  object-fit: cover;
  object-position: center;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-hero-scrim {
  background: var(--a26-hero-scrim);
  grid-area: 1 / 1;
  height: 100%;
  pointer-events: none;
  position: relative;
  width: 100%;
  z-index: 1;
}
/* The stack sits just below the frame's centre on both boards: LTL-0 spans
   y=249..369 of 548 (centre 56.4%), LTK-0 y=325..623 of 899 (centre 52.7%).
   Centring plus a percentage nudge reproduces that at any frame height without
   a magic top value. */
html[data-brand="aktiv-2026"] .a26h-hero-text {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
  grid-area: 1 / 1;
  justify-content: center;
  padding-inline: var(--a26-gutter);
  position: relative;
  text-align: center;
  transform: translateY(6%);
  width: 100%;
  z-index: 2;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-hero-text {
    gap: var(--a26-s-7);
    transform: translateY(3%);
  }
}
/* "Promopakke for" — h3. It carried its own kicker rung (18/21 on phones)
   until D5 folded it onto h3 24/28: one increment, and h3 is already the
   rung's desktop value (32/37), so the fold cost the page a size and changed
   nothing above 1024. */
html[data-brand="aktiv-2026"] .a26h-hero-kicker {
  color: var(--a26-on-dark);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h3);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h3);
}
/* The locality — h1, reversed. */
html[data-brand="aktiv-2026"] .a26h-hero-locality {
  color: var(--a26-on-dark);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h1);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h1);
}

/* ---- Top bar. Both boards draw it OVER the photo, not as a page-level bar,
        and neither makes it sticky. It stays a <header> sibling of <main> so
        the banner and the main landmark are not nested. -------------------- */
/* Three tracks rather than space-between: both boards centre the wordmark on
   the PAGE, not between its two unequal neighbours (LTK-0 puts it at x=629 of
   1440, dead centre for its 181px width). */
html[data-brand="aktiv-2026"] .a26h-topbar {
  align-items: center;
  column-gap: var(--a26-s-3);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  inset-inline: 0;
  padding-block: var(--a26-s-5);
  padding-inline: var(--a26-s-4);
  position: absolute;
  top: 0;
  z-index: 2;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-topbar {
    padding-block: var(--a26-s-5);
    padding-inline: var(--a26-gutter);
  }
}
/* "Boligpromo" — Aktiv Sans, sentence case, untracked, in the reversal colour:
   LTK-0 draws it 20/26, LTL-0 14/18. It is NOT an eyebrow: no Fremover, no
   caps, no tracking. ONE rung now: ui 16/20 at every width. D5 folded the old
   14 on phones and the old 20 on desktop onto it — the top bar is chrome, and
   chrome on this page is the ui rung. */
html[data-brand="aktiv-2026"] .a26h-topbar-word {
  color: var(--a26-on-dark);
  flex-shrink: 0;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  letter-spacing: 0;
  line-height: var(--a26-lh-ui);
  text-transform: none;
}
/* Phone: the word is OUT (Henrik, 2026-09-12). Three marks across a 428 bar
   already cost the status pill its place in the bar (§19.2); the word is the
   next one to go, and what is left is the wordmark alone — the mark that says
   whose page this is. It stays in the DOM: the desktop rule above is the
   authority, and a `display: none` here is the whole phone behaviour.
   The bar is a THREE-TRACK grid (1fr auto 1fr) and the wordmark is centred by
   sitting in the middle track. With the word and the bar pill both out of
   flow, auto-placement would slide the wordmark into track 1 and it would no
   longer be centred, so the phone rule pins it to track 2 explicitly. */
@media (max-width: 1023px) {
  html[data-brand="aktiv-2026"] .a26h-topbar-word {
    display: none;
  }
  html[data-brand="aktiv-2026"] .a26h-wordmark {
    grid-column: 2;
  }
}
/* The centred wordmark. Both boards fill it #E9E2DD, a warm near-white; the
   asset lib/brand-assets.ts resolves is the dark lockup, so it is inverted and
   held just under full white to land on the boards' value. Sized 160x42 on
   LTL-0 and 181x47 on LTK-0; the 305:80 box is declared so the bar cannot
   reflow while the file is in flight. */
html[data-brand="aktiv-2026"] .a26h-wordmark {
  aspect-ratio: 305 / 80;
  display: block;
  filter: brightness(0) invert(1);
  height: 42px;
  object-fit: contain;
  opacity: 0.92;
  width: auto;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-wordmark {
    height: 47px;
  }
}
/* The status pill — the button device's box, outlined in the reversal colour
   and CHAMFERED: the agency board draws Aktiv's four-corner cut on "Klar til
   deling", and the 2026-09-05 ruling that reserved the chamfer for the contact
   pair was simply wrong about this one control (Henrik, 2026-09-10). Same cut
   as the pair (--a26-chamfer — the video's hero pill takes the same device,
   board.tsx CHAMFER_BUTTON_OUTPUT_PX; the web token went 4 -> 5 on
   2026-09-12, Henrik asked for the cut to read slightly more), and
   the pair's notch is NOT part of it: that V is the joined pair's own device.
   Not interactive: no hover, no press.

   HOW THE RING IS DRAWN. The pair paints the ink on the element and lays a
   1px-inset canvas fill over it (clip-path: inherit). This pill cannot: it
   sits over the property's hero photo at BOTH placements, so its interior has
   to stay see-through, and a clip-path on the element itself would cut the
   label away with the interior. So the ring is a `::before` overlay carrying
   the ink, with the interior punched out of the same clip-path by an evenodd
   fill rule — outer boundary = the pair's polygon minus the notch, inner
   boundary = exactly what the pair's inset-1px `::before` describes, so the
   two chamfered controls are one device down to the corner join. The whole
   thing is behind @supports, and where the fill rule is unsupported the pill
   keeps the square 1px border it had — the element's border stays in the box
   (transparent) either way, so the 48px box and the 20px text inset never
   move.

   TWO PLACEMENTS, ONE SHOWN. The markup draws it twice (A26StatusPill) and
   exactly one copy is displayed, so the a11y tree only ever holds one status:

     --bar   the boards' placement, in the top bar's right track. ≥1024 only.
     --hero  the phone's, centred in the hero under the postnummer · sted line.
             Three marks across a 428px bar read as crammed (Henrik,
             2026-09-08), so below 1024 the bar keeps "Boligpromo" and the
             wordmark and the status comes down here — where it gets the FULL
             control box (48 high, 1px outline, ui 16) rather than the bare
             label + dot the bar used to squeeze in.

   `display: none` on the copy that is not in play is what keeps it out of the
   accessibility tree; `visibility` or opacity would leave a second status for
   a screen reader to read out. */
html[data-brand="aktiv-2026"] .a26h-statuspill {
  align-items: center;
  border: var(--a26-hairline-w) solid var(--a26-on-dark);
  border-radius: var(--a26-radius-control);
  color: var(--a26-on-dark);
  flex-shrink: 0;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  gap: var(--a26-s-3);
  line-height: var(--a26-lh-ui);
  min-height: var(--a26-control-h);
  padding-inline: var(--a26-control-pad);
  position: relative;
}
/* The chamfer. `evenodd` in a clip-path polygon is what punches the interior
   back out, so the guard tests exactly that and nothing else — no fill rule,
   no chamfer, and the square border above still draws the pill. */
@supports (clip-path: polygon(evenodd, 0 0, 1px 0, 0 1px)) {
  html[data-brand="aktiv-2026"] .a26h-statuspill {
    /* The border stays, for the box and the text inset; the ring is the ink. */
    border-color: transparent;
  }
  html[data-brand="aktiv-2026"] .a26h-statuspill::before {
    /* The inner ring's cut: a 1px INWARD offset of the outer 45-degree corner,
       which lands at chamfer + sqrt(2) - 1, not chamfer + 1. Declared on the
       ring itself rather than in `:root` so the chamfer token keeps exactly
       two readers — the pair and this pill. */
    --a26-chamfer-in: calc(var(--a26-chamfer) + 0.41421356px);
    background-color: var(--a26-on-dark);
    clip-path: polygon(
      evenodd,
      /* --- OUTER: the octagon. The pair's polygon without the pair's notch. */
      var(--a26-chamfer) 0,
      calc(100% - var(--a26-chamfer)) 0,
      100% var(--a26-chamfer),
      100% calc(100% - var(--a26-chamfer)),
      calc(100% - var(--a26-chamfer)) 100%,
      var(--a26-chamfer) 100%,
      0 calc(100% - var(--a26-chamfer)),
      0 var(--a26-chamfer),
      /* --- THE SLIT, out to the inner ring and, at the end, back along the
         same line. `polygon()` is ONE closed path, so an evenodd ring has to
         reach its inner boundary somehow, and the segment it travels on must
         enclose no area or evenodd flips the fill beside it. Round 4 ran the
         two joins to DIFFERENT points — out from `0 chamfer` to the inner
         top-edge vertex, home from the inner left-edge vertex to `chamfer 0`
         — and those two lines cross at the middle of the top-left cut. Two
         wedges of the ring flipped to empty there and the cut came out as a
         fat blob, a gap and a triangle: Henrik's dent (2026-09-12). Out and
         home on ONE segment is the fix; it lies inside the ring the whole
         way, so it paints nothing and punches nothing. */
      var(--a26-hairline-w) var(--a26-chamfer-in),
      /* --- INNER: the same octagon offset 1px INWARD, which is why the cut
         reads `chamfer + 0.41` and not `chamfer + 1`. A 45-degree corner
         offset by 1 moves its line to x + y = chamfer + sqrt(2), so the
         vertex on the top edge sits at chamfer + sqrt(2) - 1. `chamfer + 1`
         put that line at chamfer + 2 and made the diagonal 1.41px of ink
         against the straight edges' 1 — the same error the pair's `clip-path:
         inherit` made in the other direction, and the reason the pair carries
         offset literals rather than the outer numbers. */
      var(--a26-chamfer-in) var(--a26-hairline-w),
      calc(100% - var(--a26-chamfer-in)) var(--a26-hairline-w),
      calc(100% - var(--a26-hairline-w)) var(--a26-chamfer-in),
      calc(100% - var(--a26-hairline-w)) calc(100% - var(--a26-chamfer-in)),
      calc(100% - var(--a26-chamfer-in)) calc(100% - var(--a26-hairline-w)),
      var(--a26-chamfer-in) calc(100% - var(--a26-hairline-w)),
      var(--a26-hairline-w) calc(100% - var(--a26-chamfer-in)),
      /* inner ring closed, then home down the slit */
      var(--a26-hairline-w) var(--a26-chamfer-in),
      0 var(--a26-chamfer)
    );
    content: "";
    inset: 0;
    pointer-events: none;
    position: absolute;
  }
}
/* Phone: the hero copy is on, the bar copy is out. */
html[data-brand="aktiv-2026"] .a26h-statuspill--bar {
  display: none;
}
html[data-brand="aktiv-2026"] .a26h-statuspill--hero {
  align-self: center;
  display: inline-flex;
  justify-content: center;
  margin-block-start: var(--a26-s-2);
}
@media (min-width: 1024px) {
  /* Desktop: back to the boards — the bar carries it, the hero does not. */
  html[data-brand="aktiv-2026"] .a26h-statuspill--bar {
    display: flex;
    justify-self: end;
  }
  html[data-brand="aktiv-2026"] .a26h-statuspill--hero {
    display: none;
  }
}
/* The dot breathes: opacity 1 -> 0.55 -> 1 over one slow cycle, opacity ONLY
   (the aktiv-2019 dot scales; nothing here moves). Green is status, and a
   live "ready" signal is status, not decoration — Henrik 2026-09-06, graphics
   device spec §6.4. Off under reduced motion (the kill switch at the end). */
@keyframes a26h-dotpulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.55;
  }
}
html[data-brand="aktiv-2026"] .a26h-statusdot {
  animation: a26h-dotpulse var(--dur-a26-pulse) var(--ease-a26-micro) infinite;
  background-color: var(--a26-green);
  border-radius: 50%;
  display: block;
  flex-shrink: 0;
  height: var(--a26-dot);
  width: var(--a26-dot);
}

/* ============================================================================
   MEDIA — the boards' video preview (05, 06). The graphics have their own
   device further down (08). Flat: no shadow (the boards draw one on the FB
   thumbnail; the design language retires elevation — deviation logged).
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-media {
  background-color: var(--a26-media-ground);
  border: none;
  border-radius: var(--a26-radius-media);
  cursor: pointer;
  display: block;
  overflow: hidden;
  padding: 0;
  position: relative;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-media-inner {
  display: block;
  height: 100%;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-media > img,
html[data-brand="aktiv-2026"] .a26h-media > video,
html[data-brand="aktiv-2026"] .a26h-media-inner > img,
html[data-brand="aktiv-2026"] .a26h-media-inner > video {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-media--wide {
  aspect-ratio: var(--a26-video-wide-aspect);
}
html[data-brand="aktiv-2026"] .a26h-media--tall {
  aspect-ratio: var(--a26-video-tall-aspect);
  max-width: var(--a26-story-w);
}
/* The play disc — LTL-0 64px with a 16x19 triangle, LTK-0 96px with 24x28. */
html[data-brand="aktiv-2026"] .a26h-playchip {
  align-items: center;
  background-color: var(--a26-playchip);
  border-radius: 50%;
  display: flex;
  height: var(--a26-s-8);
  inset: 0;
  justify-content: center;
  margin: auto;
  pointer-events: none;
  position: absolute;
  transition: transform var(--dur-micro) var(--ease-a26);
  width: var(--a26-s-8);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-playchip {
    height: var(--a26-s-9);
    width: var(--a26-s-9);
  }
}
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-media:hover .a26h-playchip {
    transform: scale(1.06);
  }
}
/* The play triangle is a MARK, not text, so it takes the chrome ink rather
   than the retired --a26-ink-deep (#1F1410, a third near-ink). */
html[data-brand="aktiv-2026"] .a26h-playchip svg {
  fill: var(--a26-ink-chrome);
  height: 19px;
  margin-left: 3px;
  width: 16px;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-playchip svg {
    height: 28px;
    width: 24px;
  }
}
/* The story preview's app chrome (LTK-0 section 06 draws the tall preview as
   an Instagram story: a progress bar, the poster's avatar and name, a reply
   field and two glyphs at the foot). Decorative and inert: it sits over the
   film, takes no pointer, and is hidden from assistive technology. */
html[data-brand="aktiv-2026"] .a26h-story {
  color: var(--a26-on-dark);
  display: flex;
  flex-direction: column;
  inset: 0;
  justify-content: space-between;
  padding: var(--a26-s-3);
  pointer-events: none;
  position: absolute;
}
/* A floor under the story's name row, the hero scrim's own colour, so the
   reversal type reads over a bright still. NEUTRAL BLACK since B&Y round 1
   (2026-09-14) — it ramps to zero, so its 0.45 head is a type floor and not a
   filter over the picture. */
html[data-brand="aktiv-2026"] .a26h-story-top {
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0) 100%);
  display: block;
  margin: calc(var(--a26-s-3) * -1) calc(var(--a26-s-3) * -1) 0;
  padding: var(--a26-s-3) var(--a26-s-3) var(--a26-s-5);
}
html[data-brand="aktiv-2026"] .a26h-story-bar {
  background-color: rgba(250, 245, 240, 0.35);
  display: block;
  height: 2px;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-story-bar > span {
  background-color: var(--a26-on-dark);
  display: block;
  height: 100%;
  width: 40%;
}
html[data-brand="aktiv-2026"] .a26h-story-head,
html[data-brand="aktiv-2026"] .a26h-story-foot {
  align-items: center;
  display: flex;
  gap: var(--a26-s-2);
}
html[data-brand="aktiv-2026"] .a26h-story-head {
  padding-top: var(--a26-s-2);
}
/* The story chrome's initials — the same deliberate exception as .a26h-avatar
   above: Varighet at the mono size inside an aria-hidden drawing of another
   app's UI. The two story text lines below take the mono size in the Sans
   face for the same reason. */
html[data-brand="aktiv-2026"] .a26h-story-avatar {
  align-items: center;
  background-color: var(--a26-peach);
  border-radius: 50%;
  color: var(--a26-text);
  display: flex;
  flex-shrink: 0;
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-mono);
  height: var(--a26-s-5);
  justify-content: center;
  line-height: 1;
  width: var(--a26-s-5);
}
html[data-brand="aktiv-2026"] .a26h-story-name,
html[data-brand="aktiv-2026"] .a26h-story-time {
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-mono);
  line-height: var(--a26-lh-mono);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
html[data-brand="aktiv-2026"] .a26h-story-time {
  opacity: 0.7;
}
html[data-brand="aktiv-2026"] .a26h-story-reply {
  border: var(--a26-hairline-w) solid rgba(250, 245, 240, 0.7);
  border-radius: var(--a26-s-5);
  flex-grow: 1;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-mono);
  line-height: var(--a26-lh-mono);
  min-width: 0;
  overflow: hidden;
  padding: var(--a26-s-1) var(--a26-s-3);
  text-overflow: ellipsis;
  white-space: nowrap;
}
html[data-brand="aktiv-2026"] .a26h-story-foot svg {
  flex-shrink: 0;
  height: var(--a26-s-4);
  width: var(--a26-s-4);
}

/* ============================================================================
   THE FILM'S OPENING FRAME, over the video previews' poster (05, 06).

   Henrik, 2026-09-12: the videos are the key moment and their thumbnails are
   a bland photo. So the poster carries the three things the a26 BoligPromo
   comp puts on screen at second one — see components/boligpromo-a26/
   A26ThumbOverlay.tsx for the transcription and the `?thumb=a|b|off` switch.

   EVERY NUMBER BELOW IS THE COMP'S, not this stylesheet's taste:

     the plate's cut          `board.tsx CHAMFER_PHOTO_OUTPUT_PX` = 12, one
                              value for both frames, as the film has one
     the pill's cut           `A26_HERO_PILL_CHAMFER_RATIO` = 0.375 of the
                              pill's own HEIGHT (24 -> 9). A RATIO, because
                              the plate device is proportional where the
                              agency's button cut is fixed — which is exactly
                              why this block does NOT read `--a26-chamfer`:
                              that 5px token is the contact pair's and the
                              status pill's, and the invariants test keeps it
                              to those two controls.
     the hairline             `A26_HERO_PILL_STROKE_OUTPUT_PX` = 1, i.e.
                              `--a26-hairline-w`, on plate and pill alike
     the scrim                S01's own wash (`scenes.tsx SCRIM.tall.hero`,
                              stops 0.65 / 0.15 / 0.25 at mid 40), in the warm
                              ink the hub's hero scrim already uses rather
                              than the comp's neutral — bottom-heavy under the
                              address, with a lighter return at the top for
                              the pill.

   HOW THE HAIRLINES ARE DRAWN. The same evenodd clip-path ring as
   `.a26h-statuspill` (see its note): both sit over the property photograph, so
   the interior has to stay see-through, and a clip-path on a bordered box cuts
   the border away with the corner and leaves four open gaps where the
   diagonals should be. Outer boundary = the octagon; inner boundary = the same
   octagon 1px in, whose cut is `cut + sqrt(2) - 1` because a 45-degree line
   offset by 1 perpendicular moves to x + y = cut + sqrt(2); out and home along
   ONE segment, so the connector encloses no area and evenodd cannot flip the
   fill beside it (the round-4 dent). Behind the same @supports guard, and
   where the fill rule is unsupported the plate keeps a square 1px border and
   the pill keeps its own — the device degrades to a rectangle, never to
   nothing.

   THE TYPE TAKES NO NEW RUNG. The ladder is 6 sizes at 428 and 7 at 1440
   (devices doc §2) and stays that way:

     pill label + locality   the mono rung, 12 at both widths
     street, wide frame      h2 — 28 at 428, 32 at 1440. The frame grows with
                             the column (388 -> 583), so the type may too
     street, story frame     the UI rung, 16 at both widths. The story preview
                             is a fixed 189 x 336 at EVERY viewport
                             (`--a26-story-w`), so its type is fixed too, and
                             round 3's 8px pad leaves it 157px of content —
                             enough that most streets set on ONE line and
                             Bringebaerhagen 7A stops wrapping. Two lines,
                             then ellipsis. `?tallpill=h3` measures the h3
                             rung here instead and loses at 1440, where h3 is
                             32; see the story-frame block.

   MOTION. The overlay is the PRE-ROLL: it belongs to the still, so it leaves
   when the film starts and comes back when it stops. MediaPlayButton marks its
   own playback with `data-a26-live` (the inline element only ever plays on a
   phone, where it goes to native fullscreen; on desktop the lightbox covers
   the page and this poster keeps its overlay, which is correct). Opacity only,
   `--dur-micro`, and under reduced motion the fade collapses to 0s — the
   overlay still goes, it just does not travel.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-thumb {
  /* Air between the frame's edge and the plate. */
  --a26-thumb-inset: var(--a26-s-3);
  /*
   * Air between the plate and the type inside it. ROUND 2 (Henrik, 2026-09-12:
   * «lets have some more breathing room in the corner of the wide video. looks
   * a bit crammed there»): 8 -> 16 on a phone and 12 -> 24 from 1024 up — two
   * rungs of the ladder each. The PLATE DOES NOT MOVE; the corner reads
   * composed because the stack steps away from it, not because the frame did.
   * And 16 of 291 is 5.5 % of the wide frame's height, 24 of 437 is 5.5 % —
   * the same air at both widths, which is why it is two rungs and not one.
   */
  --a26-thumb-pad: var(--a26-s-4);
  /* Extra floor under the address. 0 unless something already owns the foot. */
  --a26-thumb-floor: 0px;
  /* The comp's photo chamfer. */
  --a26-thumb-cut: 12px;
  --a26-thumb-pill-h: var(--a26-s-5);
  /*
   * 0.375 of the pill's height — the comp's hero-pill ratio
   * (`A26_HERO_PILL_CHAMFER_RATIO`). ROUND 3 DERIVES it rather than stating
   * 9px, because the story frame now runs a SHORTER pill (20 rather than 24)
   * and the ratio has to follow the height instead of being restated beside
   * it: 24 x 0.375 = 9 in the wide frame, 20 x 0.375 = 7.5 in the story one.
   * One expression, so the cut and the height can never drift apart.
   */
  --a26-thumb-pill-cut: calc(var(--a26-thumb-pill-h) * 0.375);
  /*
   * S01's own wash, in the warm ink the hub's hero scrim already uses rather
   * than the comp's neutral: a deep foot under the stack, a light belly so the
   * photograph still sings where the play disc is, and a small return at the
   * top so the plate's upper hairline has a floor to sit on.
   *
   * The foot's 0.70 is CHOSEN ON MEASUREMENT, not on taste. Worst-pixel
   * contrast of every overlay text box against the ground it actually sits on
   * (photo + every scrim, glyphs blanked so what is read is the floor), all
   * three a26 fixtures at 428 and 1440:
   *
   *   foot 0.62  worst 4.79  passes, no margin
   *   foot 0.70  worst 6.37  SHIPPED — and 0.70 is the comp's own S02 value,
   *                          a rung above its 0.65 S01 foot
   *   foot 0.78  worst 8.58  darker than the picture can afford
   *
   * The bar is 4.5:1: the pill label and the subline are 12px, which is small
   * text, so large-text 3:1 does not apply to them.
   */
/*
   * ROUND 10 (2026-09-13) ADDS THE 0.62 STOP AT 50 %, and it is a scrim fix,
   * not a composition one. The wide frame's stack is bottom-anchored, so a
   * TWO-LINE address pushes the pill up into the belly: on
   * `a26-demo-dronning-eufemias-gate-31` at 428 the «TIL SALGS» label sits
   * 43.0-47.1 % up the frame, where the old ramp had thinned to 0.47-0.56, and
   * the label measured 3.52:1 over sky (flagged as round 9's open item, and
   * present on the pristine baseline too). One-line fixtures sit at 25-36 %
   * and were never at risk.
   *
   * The band the ink can reach now holds round 3's story calibration —
   * 0.62-0.64 through the pill band — carried here as a single stop, so the
   * declaration reads 0.66 at 38 % to 0.62 at 50 % instead of falling straight
   * to 0.16. The CLEARING DID NOT MOVE: 0.16 is still at 62 % and the top
   * third of the photograph is the same picture it was. What darkens is the
   * 38-62 % belly, by at most 0.21 at the 50 % stop and nothing at either end.
   * Measured after: that label goes 3.52 -> 5.79, and the only other cell in
   * the 36-cell probe that moves at all is the same fixture's street, 6.98 ->
   * 7.08. Every wide and story cell on the other two fixtures is identical to
   * the pixel, which is what "the clearing did not move" means in numbers.
   */
/*
   * ROUND 11 (B&Y round 1, 2026-09-14) CHANGES THE HUE AND CAPS THE CLEARING,
   * and changes nothing about the type band. Two halves to the agency's note
   * (#2 and #7: «Du kan legge et svart filter over bildene, men unngå et brunt
   * filter da dette gir alt et litt retro-preg. Ville også redusert mengden
   * filter. Helst 20%, max 33%»):
   *
   *   HUE — every stop moves from the warm ink rgba(25,12,4) to a NEUTRAL
   *   rgba(0,0,0). That is the unambiguous half and it is free: black at the
   *   same alpha is marginally darker than the warm ink, so no measured
   *   contrast falls.
   *
   *   AMOUNT — the part of the frame that is purely PICTURE is what the agency
   *   is looking at when it says «20%, max 33%», and that is the clearing: the
   *   0.16 stop at 62 % and the return at 100 %. The return was 0.24 and is
   *   now 0.20, so the whole clearing is at or under the 20 % target. No type
   *   sits above 62 % in this frame (the stack is bottom-anchored, round 2), so
   *   this cap cannot touch a contrast number.
   *
   *   WHAT IS DELIBERATELY NOT REDUCED: the 0.70 / 0.66 / 0.62 band from the
   *   foot to 50 %. That is not a filter over a photograph, it is the measured
   *   legibility floor under reversal type, and the measurement below is what
   *   blocks it — foot 0.62 already measures 4.79:1 worst-pixel, i.e. AA with
   *   no margin, and 0.33 would put 12px light type far under 4.5:1 on a
   *   bright façade. Taking the type band to 20 % needs the COMPOSITION to
   *   change (B&Y #11-scale re-layout), not the scrim. Logged as held.
   */
  --a26-thumb-scrim: linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.7) 0%,
    rgba(0, 0, 0, 0.66) 38%,
    rgba(0, 0, 0, 0.62) 50%,
    rgba(0, 0, 0, 0.16) 62%,
    rgba(0, 0, 0, 0.2) 100%
  );
  /*
   * The two ends of S01's column are the two FLOW children of this box, so
   * where they sit is one property rather than four inset calcs: the wide
   * frame opens them out (`space-between` — pill top-left, address
   * bottom-left), the story frame stacks them at the foot the way the comp
   * does. Nothing here is absolutely positioned except the two painted
   * layers, which means a two-line address pushes the pill nowhere and a
   * one-line address leaves no hole.
   */
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  /*
   * PILL -> ADDRESS. The comp's own share of the frame put this at 4 on a
   * phone and 7-8 from 1024 up (S01's `L.hero.gap` is 28 board px of 1920 =
   * 1.46 % tall, 36 of 2208 = 1.63 % wide). Round 2 sets it to ONE RUNG — 8 —
   * at every width: the share derivation is right about a 1080-wide film and
   * wrong about a 189-wide preview, and 4px between a 24px pill and a 28px
   * display line is what «crammed» meant. The gap is now format-invariant,
   * so the desktop block below no longer needs to say anything about it.
   */
  gap: var(--a26-s-2);
  inset: 0;
  justify-content: flex-end;
  padding: calc(var(--a26-thumb-inset) + var(--a26-thumb-pad));
  padding-block-end: calc(
    var(--a26-thumb-inset) + var(--a26-thumb-pad) + var(--a26-thumb-floor)
  );
  pointer-events: none;
  position: absolute;
  /* A <button> centres its text; this box sets ragged-right, as S01 does. */
  text-align: start;
  transition: opacity var(--dur-micro) var(--ease-a26-micro);
  /* Under the play disc, which is the only operable thing in this box. */
  z-index: 0;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-thumb {
    --a26-thumb-inset: var(--a26-s-4);
    --a26-thumb-pad: var(--a26-s-5);
  }
}
/*
 * ---- The story frame, ROUND 3: centred on the disc ------------------------
 *
 * Henrik, 2026-09-12: «the tall format thumbnail overlay isn't well balanced.
 * the pill label is too big compared to the address. and the chamfer line is
 * maybe a bit too much into the frame. should have less padding on all sides.
 * could go for a more centered approach with this, and have the til salgs pill
 * over the play button and the address more centered underneath it»
 *
 * So the story frame stops copying the wide frame's corner column and becomes
 * its own composition — a TITLE CARD. The wide frame is untouched: Henrik
 * approved it in round 2, and every declaration below is inside a
 * `.a26h-thumb--tall` selector.
 *
 * THE AXIS IS THE PLAY DISC, not the plate. `.a26h-playchip` is
 * `inset: 0; margin: auto` inside `.a26h-media`, i.e. dead-centre of the 189 x
 * 336 frame at both widths (64 on a phone, 96 from 1024 up). A centred stack
 * whose middle term is that disc therefore has to be built around the disc's
 * own band, which is what the grid below does:
 *
 *     grid-template-rows: 1fr <disc> 1fr
 *
 * Two equal `1fr` rows put the middle track exactly in the middle of the
 * content box — and because the padding is symmetric on all four sides
 * (`--a26-thumb-floor` is 0 here), the middle of the content box IS the middle
 * of the frame. The middle track is left EMPTY and sized to the disc, so the
 * disc lands in it without this overlay ever positioning it: the pill takes
 * row 1 at its foot, the address takes row 3 at its head, and `row-gap` is
 * then the ONE number that sets both the pill -> disc and the disc -> address
 * distance. Equal by construction rather than by two matching calcs.
 *
 * WHY THE GAP IS 12 AND NOT 8. Both fit — the arithmetic below has 33-56 px to
 * spare either way — so this is an optical choice with a reason. 8 is now the
 * EDGE air (inset and pad, Henrik's «less padding on all sides»), and reusing
 * it inside the group would leave the composition with a single undifferentiated
 * air value: the pill would sit as far from the disc as the plate sits from the
 * frame. 12 is this device's own module — it is `--a26-thumb-cut`, the comp's
 * `CHAMFER_PHOTO_OUTPUT_PX`, the corner the plate is cut with — so the group's
 * internal step is the frame's own step, one rung above its edge air. It also
 * survives the disc: 8 between a 1px-outline pill and a 96px SOLID light disc
 * reads as about 5, because the disc carries its own optical mass (and a
 * `scale(1.06)` hover that eats 3 px of it); 12 keeps pill, disc and address
 * as three separate reads at 336 px tall.
 *
 * PAD AND INSET 12 -> 8, all four sides («the chamfer line is maybe a bit too
 * much into the frame. should have less padding on all sides»). That is one
 * rung down on each, and it is a net GAIN of information: the street now has
 * 189 - 2 x (8 + 8) = 157 px to set on instead of round 2's 141, which is what
 * puts `Bringebærhagen 7A` back on one line — round 2's own open item.
 *
 * THE ARITHMETIC. Content box 157 x 304, top y 16, foot y 320. Plate inner
 * edge (inset 8 + 1px hairline) at y 327.
 *
 *   phone, disc 64    1fr = (304 - 64 - 2 x 12) / 2 = 108
 *                     pill  y 104-124   disc y 136-200   address from y 212
 *   desktop, disc 96  1fr = (304 - 96 - 2 x 12) / 2 = 92
 *                     pill  y  88-108   disc y 120-216   address from y 228
 *
 * The disc bands are the real disc: (336 - 64) / 2 = 136 and (336 - 96) / 2 =
 * 120. The grid did not place the disc — it agrees with it, which is the check
 * that the composition is actually disc-axial.
 *
 * THE SUBLINE COMES BACK. Rounds 1 and 2 dropped `0194 · OSLO` from this frame
 * because the bottom-anchored stack had 5 px of clearance to the disc. The
 * centred stack does not queue against the disc at all — the address grows
 * DOWN into 92-108 px of its own row — so the question is a fresh one, and the
 * measurement answers it: the worst case (two street lines + subline = 20 + 20
 * + 4 + 15 = 59) ends at y 287 on desktop and y 271 on a phone, i.e. 40 and 56
 * px clear of the plate, against the brief's 12 px bar. It fits with room, so
 * the film's third line is restored and this frame says what the wide one says.
 * Only the chrome reference keeps dropping it (see the `:has()` rule below),
 * because its budget is the one that could not afford it.
 */
html[data-brand="aktiv-2026"] .a26h-thumb--tall {
  --a26-thumb-inset: var(--a26-s-2);
  --a26-thumb-pad: var(--a26-s-2);
  /*
   * THE WASH, RE-WEIGHTED. The wide frame's scrim is bottom-heavy with a light
   * belly because all of its ink is in one corner. This frame's ink is now
   * spread from y 88 to y 287 — straight through that belly — and the pill has
   * moved from the darkest part of the wash into a band that measures 0.17
   * alpha under the wide frame's stops, over sky. Round 1 established what
   * that costs: 12px light type on a 0.16-0.24 wash over a bright photograph
   * runs 2.56-4.20:1.
   *
   * So the story frame overrides the gradient, and only the story frame. The
   * stops are round 1's own calibration curve re-used rather than re-guessed:
   * a foot of 0.62 measured 4.79:1 worst-pixel and 0.70 measured 6.37, so
   * ~0.62 is the alpha a text box needs to clear 4.5 over the worst of the
   * three fixtures. The pill band (63-74 % up on a phone, 68-74 % on desktop)
   * therefore gets 0.62-0.64 instead of 0.17, the foot keeps its 0.70, and the
   * clearing moves to the top sixth — above the plate, where nothing is set.
   *
   * It is a heavier frame than round 2's. That is the price of a centred
   * composition on a photograph: the ink no longer has a corner to hide in.
   */
  /* Neutral black and a 0.20 clearing, as the wide wash above — the type band
     (foot to 76 %) is the measured floor and holds. B&Y round 1, 2026-09-14. */
  --a26-thumb-scrim: linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.7) 0%,
    rgba(0, 0, 0, 0.66) 30%,
    rgba(0, 0, 0, 0.62) 50%,
    rgba(0, 0, 0, 0.64) 76%,
    rgba(0, 0, 0, 0.2) 100%
  );
  /* The play disc's own diameter — `.a26h-playchip`, LTL-0 64 / LTK-0 96. */
  --a26-thumb-disc: var(--a26-s-8);
  display: grid;
  /*
   * ONE full-width column, so the base rule's `justify-content: flex-end`
   * (which the wide frame needs) has no track to push around; `justify-items`
   * below does the centring. `minmax(0, …)` rather than `1fr` so the street's
   * ellipsis still has a floor to collapse against.
   */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr var(--a26-thumb-disc) 1fr;
  justify-items: center;
  row-gap: var(--a26-s-3);
  text-align: center;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-thumb--tall {
    --a26-thumb-disc: var(--a26-s-9);
  }
}
/* Row 3, at its head: the address hangs directly under the disc. */
html[data-brand="aktiv-2026"] .a26h-thumb--tall .a26h-thumb-addr {
  align-self: start;
  grid-row: 3;
  text-align: center;
}
/*
 * ---- The pill: ONE device on both frames (round 9) ------------------------
 *
 * Round 3 answered «the pill label is too big compared to the address» by
 * shrinking the BOX — 24 x 12 down to 20 x 8, chamfer 7.5. Henrik, 2026-09-13,
 * on the result: «the til salgs pill is a bit sharp on the edges and looks a
 * bit misscaled internally. looks like the text is too big for the pill. and
 * misaligned padding.»
 *
 * All three notes are the same fact. A 12 px mono label on a 15 px line box
 * inside a 20 px pill leaves 2.5 px above and below the LINE box and about
 * 4.2 px above and below the CAP — which is less air than the 8 px of side
 * padding, so the label reads as pressed against the top and bottom rails and
 * loose at the ends. And a chamfer derived from 20 is 7.5 px, which on a 20 px
 * box eats three quarters of the height at each corner: the cut stops reading
 * as a chamfer and starts reading as a point. Both are consequences of the
 * height, and the height was the round-3 change.
 *
 * So the box goes back to the wide frame's, and this block now says nothing
 * about it: `--a26-thumb-pill-h` stays `--a26-s-5` (24), `padding-inline`
 * stays `--a26-s-3` (12), and the chamfer follows the height to 9 through the
 * ratio in the base rule. ONE pill device on both frames, which is what the
 * comp draws — S01's hero pill is one object, not a tall variant and a wide
 * variant.
 *
 * The hierarchy round 3 was buying does not need the box: the address is still
 * the widest and the tallest thing in the group (a 16/20 street over a 12/15
 * subline against an 84 x 24 pill), and the pill has 12 px of clear air to the
 * disc above it. Fit re-measured, not assumed — §12.
 *
 * What is left here is the pill's POSITION in the title-card grid, which is
 * the only thing about it that is the story frame's own.
 */
html[data-brand="aktiv-2026"] .a26h-thumb--tall .a26h-thumb-pill {
  /* Row 1, at its foot: the pill sits directly over the disc. */
  align-self: end;
  grid-row: 1;
}
/*
 * THE REFERENCE, KEPT AND SELF-RESTORING. Flip `?storychrome=1` back on and
 * the chrome returns to the DOM as a following sibling of this overlay — and
 * these rules then hand the frame back its ROUND-2 CORNER LAYOUT, so the
 * centred stack and Instagram's chrome can never be on screen together. The
 * corner layout is what round 2 measured against that chrome: flex column,
 * bottom-anchored and ragged-left, inset 12, pad 8, gap 4, floor 24, subline
 * dropped -> pill 24 + 4 + two street lines 40 = 68 in the 83px window between
 * the desktop disc (ends 216) and the reply row (starts 299), block y 224-292,
 * clear of the disc by 8 and of the row by 7.
 *
 * Note what is NOT reverted: the pill's own 20 / 8 box and the re-weighted
 * wash stay. The chrome switch is a layout reference, not a time machine — and
 * both of those are improvements Henrik asked for in this round, not part of
 * the geometry the chrome constrains.
 *
 * If `:has()` is unsupported these rules drop and `?storychrome=1` renders the
 * centred stack under the chrome, whose reply row it overlaps. That is a
 * preview-only switch in a browser generation older than 2023, and the
 * SHIPPING path — chrome off — does not use these rules at all, which is why
 * the centred layout is the plain rule and the reference is the qualified one.
 */
html[data-brand="aktiv-2026"] .a26h-thumb--tall:has(~ .a26h-story) {
  --a26-thumb-inset: var(--a26-s-3);
  --a26-thumb-pad: var(--a26-s-2);
  --a26-thumb-floor: var(--a26-s-5);
  gap: var(--a26-s-1);
  display: flex;
  text-align: start;
}
html[data-brand="aktiv-2026"] .a26h-thumb--tall:has(~ .a26h-story) .a26h-thumb-pill,
html[data-brand="aktiv-2026"] .a26h-thumb--tall:has(~ .a26h-story) .a26h-thumb-addr {
  /*
   * In a flex column `align-self` is the CROSS axis, i.e. horizontal: left as
   * `end` the pill would fly to the right edge. `auto` hands both boxes back
   * to the base rule's `align-items: flex-start`. `grid-row` needs no reset —
   * a flex container ignores it.
   */
  align-self: auto;
  text-align: start;
}
/*
 * AND THE CHROME REFERENCE STILL DROPS THE SUBLINE. Its budget is the one that
 * could not afford it: bottom-anchored against a reply row, adding `0194 ·
 * OSLO` is 4 + 15 = 19 more, which put the two-line stack's top at y 221
 * against a desktop disc ending at 216. The shipping path — the centred stack
 * above — has 40 px of room and keeps the line.
 *
 * `display: none`, not `visibility`: the whole overlay is aria-hidden, so this
 * is only about not reserving a box.
 */
html[data-brand="aktiv-2026"] .a26h-thumb--tall:has(~ .a26h-story) .a26h-thumb-locality {
  display: none;
}
/*
 * ---- `?tallpill=h3` — the measured alternative ---------------------------
 *
 * The other way to make the address out-rank the pill: leave the pill at the
 * wide frame's 24 / 12 and put the street on the h3 rung instead of the UI
 * rung. Henrik asked for both to be measured, so this is the second one,
 * behind a review switch for one round.
 *
 * It loses on fit, not on taste. `--a26-t-h3` is 24 on a phone but **32 from
 * 1024 up**, and this frame is 189 x 336 at EVERY viewport — so the desktop
 * story preview would set a 32px display line on 157 px of content. Numbers
 * in docs/plans/2026-09-12-a26-hub-video-thumbnail.md §11.4.
 */
/* ROUND 9: the pill half of this switch is gone — both branches now run the
   same 24 / 12 / 9 box, so the only thing `?tallpill=h3` still changes is the
   street's rung, which is what it was built to measure. */
html[data-brand="aktiv-2026"] .a26h-thumb--tall[data-a26-tallpill="h3"] .a26h-thumb-street {
  font-size: var(--a26-t-h3);
  line-height: var(--a26-lh-h3);
}
/* S01's wash, in the hub's warm ink. Bottom-heavy under the address, with a
   lighter return at the top for the pill — the comp's three stops. */
html[data-brand="aktiv-2026"] .a26h-thumb-scrim {
  background: var(--a26-thumb-scrim);
  display: block;
  inset: 0;
  position: absolute;
}
/* ---- The plate: the comp's chamfered photo frame, as a hairline ---------- */
html[data-brand="aktiv-2026"] .a26h-thumb-plate {
  border: var(--a26-hairline-w) solid var(--a26-on-dark);
  display: block;
  inset: var(--a26-thumb-inset);
  position: absolute;
}
@supports (clip-path: polygon(evenodd, 0 0, 1px 0, 0 1px)) {
  html[data-brand="aktiv-2026"] .a26h-thumb-plate {
    /* 1px inward offset of a 45-degree corner: cut + sqrt(2) - 1. */
    --a26-thumb-cut-in: calc(var(--a26-thumb-cut) + 0.41421356px);
    background-color: var(--a26-on-dark);
    border-color: transparent;
    clip-path: polygon(
      evenodd,
      var(--a26-thumb-cut) 0,
      calc(100% - var(--a26-thumb-cut)) 0,
      100% var(--a26-thumb-cut),
      100% calc(100% - var(--a26-thumb-cut)),
      calc(100% - var(--a26-thumb-cut)) 100%,
      var(--a26-thumb-cut) 100%,
      0 calc(100% - var(--a26-thumb-cut)),
      0 var(--a26-thumb-cut),
      /* out to the inner ring and, at the end, home along the same segment */
        var(--a26-hairline-w) var(--a26-thumb-cut-in),
      var(--a26-thumb-cut-in) var(--a26-hairline-w),
      calc(100% - var(--a26-thumb-cut-in)) var(--a26-hairline-w),
      calc(100% - var(--a26-hairline-w)) var(--a26-thumb-cut-in),
      calc(100% - var(--a26-hairline-w)) calc(100% - var(--a26-thumb-cut-in)),
      calc(100% - var(--a26-thumb-cut-in)) calc(100% - var(--a26-hairline-w)),
      var(--a26-thumb-cut-in) calc(100% - var(--a26-hairline-w)),
      var(--a26-hairline-w) calc(100% - var(--a26-thumb-cut-in)),
      var(--a26-hairline-w) var(--a26-thumb-cut-in),
      0 var(--a26-thumb-cut)
    );
  }
}
/* ---- «TIL SALGS» — S01's hero pill, top-left inside the plate ------------ */
html[data-brand="aktiv-2026"] .a26h-thumb-pill {
  align-items: center;
  border: var(--a26-hairline-w) solid var(--a26-on-dark);
  color: var(--a26-on-dark);
  display: inline-flex;
  flex-shrink: 0;
  height: var(--a26-thumb-pill-h);
  justify-content: center;
  /* The height is fixed and the label is centred in it, so any block padding
     here would only fight the centring. Stated rather than left to the UA. */
  padding-block: 0;
  padding-inline: var(--a26-s-3);
  position: relative;
}
/*
 * THE LABEL BOX (round 9). The pill is a flex row that centres this box on
 * both axes, so what the eye reads as «padding» is the distance from the rail
 * to the INK, not to the line box. Carrying the mono rung's 15 px leading
 * inside a 24 px pill put a 15 px box in the middle and left the ink's own
 * asymmetry — the mono face sets more descender than the cap needs — to decide
 * where the letters landed. `line-height: 1` hands the centring to the flex
 * box instead: the label is its em box, and nothing between the rail and the
 * cap is leading that was never asked for.
 *
 * AND NO OPTICAL NUDGE IS SHIPPED, because the measurement did not ask for
 * one. Ink bounds of «TIL SALGS» (canvas, with the 0.48 px tracking applied —
 * `measureText` ignores letter-spacing unless told, and without it the label
 * reads 2.21 px off-centre that is not there) against the pill's own box:
 * 7.46 px over the cap, 7.86 px under the baseline ink, i.e. the ink sits
 * **0.20 px** high; horizontally 13.53 / 14.11, i.e. **0.29 px** left, which
 * is half the trailing letter-space and nothing else. Both are under the
 * half-pixel bar this round set for correcting, so the box is centred and left
 * alone. The numbers are recorded so the next round does not re-derive them.
 */
html[data-brand="aktiv-2026"] .a26h-thumb-pill-label {
  font-family: var(--font-a26-mono) !important;
  font-size: var(--a26-t-mono);
  font-weight: 400 !important;
  /* The comp tracks the hero label at 0.04em, the eyebrow device's value. */
  letter-spacing: var(--a26-track-eyebrow);
  line-height: 1;
  position: relative;
  text-transform: uppercase;
  white-space: nowrap;
}
@supports (clip-path: polygon(evenodd, 0 0, 1px 0, 0 1px)) {
  html[data-brand="aktiv-2026"] .a26h-thumb-pill {
    border-color: transparent;
  }
  html[data-brand="aktiv-2026"] .a26h-thumb-pill::before {
    --a26-thumb-pill-cut-in: calc(var(--a26-thumb-pill-cut) + 0.41421356px);
    background-color: var(--a26-on-dark);
    clip-path: polygon(
      evenodd,
      var(--a26-thumb-pill-cut) 0,
      calc(100% - var(--a26-thumb-pill-cut)) 0,
      100% var(--a26-thumb-pill-cut),
      100% calc(100% - var(--a26-thumb-pill-cut)),
      calc(100% - var(--a26-thumb-pill-cut)) 100%,
      var(--a26-thumb-pill-cut) 100%,
      0 calc(100% - var(--a26-thumb-pill-cut)),
      0 var(--a26-thumb-pill-cut),
      var(--a26-hairline-w) var(--a26-thumb-pill-cut-in),
      var(--a26-thumb-pill-cut-in) var(--a26-hairline-w),
      calc(100% - var(--a26-thumb-pill-cut-in)) var(--a26-hairline-w),
      calc(100% - var(--a26-hairline-w)) var(--a26-thumb-pill-cut-in),
      calc(100% - var(--a26-hairline-w)) calc(100% - var(--a26-thumb-pill-cut-in)),
      calc(100% - var(--a26-thumb-pill-cut-in)) calc(100% - var(--a26-hairline-w)),
      var(--a26-thumb-pill-cut-in) calc(100% - var(--a26-hairline-w)),
      var(--a26-hairline-w) calc(100% - var(--a26-thumb-pill-cut-in)),
      var(--a26-hairline-w) var(--a26-thumb-pill-cut-in),
      0 var(--a26-thumb-pill-cut)
    );
    content: "";
    inset: 0;
    pointer-events: none;
    position: absolute;
  }
}
/* ---- The address ladder, bottom-left inside the plate -------------------- */
/*
 * `position: relative` IS LOAD-BEARING, and the bug it fixes is invisible in
 * the computed styles. The scrim and the plate are absolutely positioned; this
 * block was not. In one stacking context CSS paints positioned descendants
 * (step 8) AFTER in-flow content (steps 4-7), so the scrim — a 0.70 warm-ink
 * wash — was painting ON TOP of the address, not under it. Every computed
 * value read correctly (opacity 1, fill #FAF5F0) and the type still came out
 * ghosted, and the contrast probe agreed with the computed styles rather than
 * with the screen because it samples the pixels ABOVE the glyphs. Positioning
 * this block puts it in step 8 too, where DOM order decides and it is last.
 * The pill was never affected: it is already `position: relative` for its ring.
 */
html[data-brand="aktiv-2026"] .a26h-thumb-addr {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-1);
  /* The padding is the parent's, so the plate's other side is the limit. */
  max-width: 100%;
  min-width: 0;
  position: relative;
}
/* The street — S01's display line, on the rung the frame can hold.
 *
 * THE SECOND CLIPPING LINE DEVICE (round 9). `-webkit-line-clamp` is an
 * `overflow: hidden` box like the rise mask, and it was measured just as
 * tight: 0.44 px of room over the Å at 428 and 0.78 at 1440, and 0.40 / 0.60
 * under a descender — i.e. inside one device pixel of cutting on a 2x screen.
 * It gets the mask's headroom on the mask's terms: padding out, margin back,
 * so the clamp's own box and the 4 px gap to the subline do not move. Here the
 * headroom can be written in `em` directly, because unlike the mask this
 * element carries the rung's own font-size.
 */
html[data-brand="aktiv-2026"] .a26h-thumb-street {
  color: var(--a26-on-dark);
  display: -webkit-box;
  margin-block: -0.12em -0.16em;
  padding-block: 0.12em 0.16em;
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h2);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h2);
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  /* Two lines, as the comp's address ladder allows (`maxLines: 2`). */
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
/* The story frame is 189 wide at every viewport, so its street line is the UI
   rung at every viewport — 16/20, which round 3's 157px of content sets most
   streets on in ONE line, and the rest in two. */
html[data-brand="aktiv-2026"] .a26h-thumb--tall .a26h-thumb-street {
  font-size: var(--a26-t-ui);
  line-height: var(--a26-lh-ui);
}
/* "0374 · Oslo" — S01's subline, the mono rung. The same headroom as the
   street above: the mono line box is 15 on a 12 px face, which measured 0.53
   over an Å and 0.46 under a descender — positive, but inside a pixel. */
html[data-brand="aktiv-2026"] .a26h-thumb-locality {
  color: var(--a26-on-dark);
  margin-block: -0.12em -0.16em;
  padding-block: 0.12em 0.16em;
  font-family: var(--font-a26-mono) !important;
  font-size: var(--a26-t-mono);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-eyebrow);
  line-height: var(--a26-lh-mono);
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}
/* The play disc sits ABOVE the overlay — it is the operable thing here, and
   the scrim must not wash it. */
html[data-brand="aktiv-2026"] .a26h-media .a26h-playchip {
  z-index: 1;
}
/* The pre-roll leaves when the film starts, and returns on pause and on end.
   `data-a26-live` is set by MediaPlayButton from the <video>'s own events. */
html[data-brand="aktiv-2026"] [data-a26-live="on"] .a26h-thumb {
  opacity: 0;
}

/* ============================================================================
   04 — AGENT ADVICE (LTK-0 M54-0 · LTL-0 MBR-0 + MYJ-0)

   Full-bleed peach panel. LTK-0 lays it out in three columns: the quote and
   body on the left rail (x=32), the portrait at x=844 (182 wide), the agent's
   name, role and joined contact pair from x=1076. LTL-0 stacks quote and
   body, then puts the portrait beside the name/role/pair.

   Rebuilt 2026-09-05 as a CONTAINER-QUERIED grid: the text column is
   `minmax(0, 1fr)`, the portrait column is fixed, the person column has a
   floor it never shrinks under, and every text box has `min-width: 0`, so
   at no width can a column overlap its neighbour — the name wraps, the
   quote wraps, nothing collides. Below 1024 the board's stack; between 768
   and 1023 the stack with the desktop portrait size.
   ============================================================================ */
/* The band is a STAGE, not a rail section, so its air is --a26-band-stage
   (48 on phones, 96 on desktop) rather than the 32/48 + 64/64 pair it carried
   before D4. One token, symmetric, and the same pair the sharehubs' filled
   bands take. */
html[data-brand="aktiv-2026"] .a26h-advice {
  background-color: var(--a26-peach);
  container: a26-advice / inline-size;
  padding-block: var(--a26-band-stage);
  padding-inline: var(--a26-gutter);
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-advice-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: var(--a26-s-6);
}
html[data-brand="aktiv-2026"] .a26h-advice-eyebrow,
html[data-brand="aktiv-2026"] .a26h-advice-main,
html[data-brand="aktiv-2026"] .a26h-advice-meta {
  min-width: 0;
}
html[data-brand="aktiv-2026"] .a26h-advice-main {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-5);
}
/* THE BAND'S INKS (type coherence audit 2026-09-05 §3.1). What made this band
   read as a different page was never its sizes — they were all on the ladder —
   but that it carried its own ink set: the quote and the paragraphs in the
   deep ink #1F1410, the name in flat black, the role in the chrome ink. Three
   inks, none of them the convention the rest of the page keeps. It now uses
   ONE ink since B&Y round 1: headline (quote + name), running copy and the
   role line all read --a26-text / --a26-body / --a26-ink-chrome, which are the
   same #190C04. Contrast on the peach ground: 15.51 : 1 throughout, AA + AAA
   (it was 16.99 / 10.48 / 15.51 across three inks). */
html[data-brand="aktiv-2026"] .a26h-quote {
  color: var(--a26-text);
  max-width: 740px;
}
html[data-brand="aktiv-2026"] .a26h-advice-body {
  color: var(--a26-body);
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
  max-width: 760px;
}
html[data-brand="aktiv-2026"] .a26h-advice-body .a26h-body {
  color: inherit;
}
/* The person row: a fixed portrait column and a text column that can only
   shrink, never overlap. */
html[data-brand="aktiv-2026"] .a26h-advice-person {
  align-items: start;
  column-gap: var(--a26-s-5);
  display: grid;
  grid-template-columns: var(--a26-portrait-w) minmax(0, 1fr);
}
/* 123x153 on LTL-0, 182x227 on LTK-0 — both 4:5, square corners (the design
   language keeps photos on info surfaces rectangular). */
html[data-brand="aktiv-2026"] .a26h-advice-pic {
  display: block;
  min-width: 0;
}
html[data-brand="aktiv-2026"] .a26h-advice-photo {
  aspect-ratio: var(--a26-portrait-aspect);
  display: block;
  object-fit: cover;
  object-position: center;
  width: var(--a26-portrait-w);
}
html[data-brand="aktiv-2026"] .a26h-advice-meta {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-1);
}
html[data-brand="aktiv-2026"] .a26h-advice-name {
  overflow-wrap: anywhere;
}
html[data-brand="aktiv-2026"] .a26h-advice-role {
  padding-bottom: var(--a26-s-3);
}
@container a26-advice (min-width: 768px) {
  html[data-brand="aktiv-2026"] .a26h-advice-person {
    column-gap: var(--a26-s-6);
  }
}
/* 960 = the content box of a 1024 viewport, so the columns arrive on the same
   step as the rail and the desktop ladder. */
@container a26-advice (min-width: 960px) {
  /* LTK-0's three columns as ratios of the 1376 content width: text 812,
     portrait 182 at x=844, the agent block from 1076 (a 50px inset) to the
     right margin. The person column is 24cqw (330 at 1440, the board's 332)
     with a 280px floor so the 203px pair and a wrapped name always fit; the
     text column takes whatever is left, and it is `minmax(0, …)` so a long
     word cannot push it wider than its track. */
  html[data-brand="aktiv-2026"] .a26h-advice-inner {
    column-gap: 0;
    grid-template-areas:
      "eyebrow eyebrow eyebrow"
      "main pic meta";
    grid-template-columns: minmax(0, 1fr) var(--a26-portrait-w) minmax(280px, 24cqw);
    row-gap: var(--a26-s-7);
  }
  html[data-brand="aktiv-2026"] .a26h-advice-eyebrow {
    grid-area: eyebrow;
  }
  html[data-brand="aktiv-2026"] .a26h-advice-main {
    grid-area: main;
    padding-right: var(--a26-s-6);
  }
  html[data-brand="aktiv-2026"] .a26h-advice-person {
    display: contents;
  }
  html[data-brand="aktiv-2026"] .a26h-advice-pic {
    grid-area: pic;
  }
  html[data-brand="aktiv-2026"] .a26h-advice-meta {
    grid-area: meta;
    padding-left: clamp(var(--a26-s-5), 3.6cqw, 50px);
  }
}

/* ---- The joined contact pair. Both boards draw ONE outline around two
        halves, meeting in a small V notch at the midpoint: 203x37 on LTL-0,
        202x36 on LTK-0. The outline is a single clip-path polygon painted the
        chrome ink, with a 1px-inset canvas fill over it. Hover fills the
        hovered half with the stroke's own ink.

        THIS IS THE VISNING HUB'S `.a26-pill`, not a cousin of it (Henrik,
        2026-09-11: "Kaisa's buttons look well spaced, and the others look a
        bit crammed"). Three things differed, and all three made this one
        tighter:
          - the halves had 8px of side air (`--a26-s-2`) against visning's 11,
          - the pair was `width: 100%; max-width: 203px` — a FIXED 203 box the
            content had to fit inside, where visning is `width: fit-content;
            min-width: 202px; max-width: 100%` — a 202 FLOOR the content may
            push past. At 16px the four-pair number plus 22px of padding wants
            221.19, so the old box was 18px short and `text-overflow` was
            quietly clipping "Send e-post" (measured: scrollWidth 102 in a
            101px client box, both viewports),
          - the box was 40 tall on phones where visning's is 44.
        Now: same tokens, same construction, same measured 221.19x40 / x44.

        ONE DELIBERATE DEVIATION, and it is about WHERE the two controls sit.
        The visning pill lives in a full-width centred column, so its 202px
        floor always has room (280 at the narrowest phone). This pair sits in
        the advice panel's meta column BESIDE the portrait — `123px 133px` at a
        320 viewport — and `min-width` beats `max-width` in CSS, so a flat
        202px floor spilled 69px past that column (clipped by the page's
        `overflow-x: clip`, so the e-mail half was simply cut off, no scrollbar
        to reveal it). Measured: it bites below roughly a 408px viewport, i.e.
        on every iPhone narrower than the 428 board. So the floor is
        `min(202px, 100%)` — 202 wherever the column can hold it, which is the
        whole desktop band and the 428 board (both measure 221.19, the floor
        never in play), and the column's own width below that, where the halves
        ellipsise as they did before. `min-width: 0` + ellipsis on the halves is
        kept from the old rule for the same reason. ---- */
html[data-brand="aktiv-2026"] .a26h-contactpair {
  align-items: stretch;
  background-color: var(--a26-ink-chrome);
  box-sizing: border-box;
  clip-path: polygon(
    var(--a26-chamfer) 0,
    calc(50% - var(--a26-notch)) 0,
    50% var(--a26-chamfer),
    calc(50% + var(--a26-notch)) 0,
    calc(100% - var(--a26-chamfer)) 0,
    100% var(--a26-chamfer),
    100% calc(100% - var(--a26-chamfer)),
    calc(100% - var(--a26-chamfer)) 100%,
    calc(50% + var(--a26-notch)) 100%,
    50% calc(100% - var(--a26-chamfer)),
    calc(50% - var(--a26-notch)) 100%,
    var(--a26-chamfer) 100%,
    0 calc(100% - var(--a26-chamfer)),
    0 var(--a26-chamfer)
  );
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: var(--a26-pair-h);
  max-width: 100%;
  min-width: min(202px, 100%);
  padding: var(--a26-hairline-w);
  position: relative;
  width: fit-content;
}
/* 44 on the mobile grammar band, as the visning pill does it: the BOX grows.
   A pseudo hit box cannot do this job here — `clip-path` clips descendants,
   pseudos included, so the `::after` this rule replaced (inset -2 block) was
   being trimmed back to the outline and never delivered the 44 it claimed. */
@media (max-width: 1023px) {
  html[data-brand="aktiv-2026"] .a26h-contactpair {
    height: var(--a26-tap);
  }
}
/* The interior: inset 1px on every side INCLUDING along the angles, which is
   why its own cut and notch numbers are not the outer ones. `clip-path:
   inherit` was the old construction and it is subtly wrong — inheriting the
   outer polygon insets the straight edges by 1px but leaves the 45-degree
   cuts on their original line, so the stroke thinned at all four corners and
   in the notch. 4.41 / 3.57 / 5.94 are what a 1px INWARD offset of those
   angles measures at the 5px cut (3.41 / 3.5 / 4.67 were the same offsets at
   the old 4px one). They are literals rather than `calc()` on the chamfer for
   the same reason they are there: an inward offset of a 45-degree corner is
   NOT the corner minus 1. The three come out of the offset lines —
   corner = chamfer + sqrt(2) - 2 in this box's own coordinates, and the notch
   pair from offsetting the V's two edges by 1 with the notch half-width at 3
   — so re-derive them if the chamfer moves again; the status pill can write
   its corner as `calc()` because it has no notch to carry. */
html[data-brand="aktiv-2026"] .a26h-contactpair::before {
  background-color: var(--a26-canvas);
  clip-path: polygon(
    0 4.41px,
    4.41px 0,
    calc(50% - 3.57px) 0,
    50% 5.94px,
    calc(50% + 3.57px) 0,
    calc(100% - 4.41px) 0,
    100% 4.41px,
    100% calc(100% - 4.41px),
    calc(100% - 4.41px) 100%,
    calc(50% + 3.57px) 100%,
    50% calc(100% - 5.94px),
    calc(50% - 3.57px) 100%,
    4.41px 100%,
    0 calc(100% - 4.41px)
  );
  content: "";
  inset: var(--a26-hairline-w);
  position: absolute;
}
html[data-brand="aktiv-2026"] .a26h-contactpair-item {
  align-items: center;
  box-sizing: border-box;
  color: var(--a26-ink-chrome);
  display: flex;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  justify-content: center;
  line-height: var(--a26-lh-ui);
  min-width: 0;
  overflow: hidden;
  padding-inline: var(--a26-pair-pad);
  position: relative;
  text-decoration: none;
  text-overflow: ellipsis;
  transition:
    background-color var(--dur-micro) var(--ease-a26-micro),
    color var(--dur-micro) var(--ease-a26-micro),
    transform var(--dur-micro) var(--ease-a26-micro);
  white-space: nowrap;
  z-index: 1;
}
/* The hovered half fills with the stroke ink; the notch geometry is the
   pair's clip-path, so the fill is clipped to the half's own outline. The
   inset is the 1px stroke on the outer edges and half the notch on the
   shared edge, so the fill meets the stroke and stops at the notch. */
@media (hover: hover) {
  html[data-brand="aktiv-2026"] a.a26h-contactpair-item:hover {
    background-color: var(--a26-hover-fill);
    color: var(--a26-hover-text);
  }
}
html[data-brand="aktiv-2026"] a.a26h-contactpair-item:active {
  transform: scale(var(--a26-press-scale));
}
html[data-brand="aktiv-2026"] .a26h-contactpair-item:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: 2px;
}

/* ============================================================================
   05 + 06 — SHARE STEPS (LTK-0 M5T-0 / M6U-0 · LTL-0 MN1-0 / MO2-0)

   The numbered serif accordion. Both boards draw the first row OPEN (headline,
   media, mono spec, copy) and the rest CLOSED — a numeral, a headline and a
   down chevron on the far right, separated by 1px chrome-ink rules. It is
   built on <details>/<summary>, so it opens with no JavaScript at all and is
   keyboard-operable by the platform.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-steps {
  display: flex;
  flex-direction: column;
}
html[data-brand="aktiv-2026"] .a26h-step {
  border-bottom: var(--a26-hairline-w) solid var(--a26-hairline);
}
html[data-brand="aktiv-2026"] .a26h-step-head {
  align-items: baseline;
  cursor: pointer;
  display: flex;
  gap: var(--a26-s-3);
  list-style: none;
  min-height: var(--a26-tap);
  padding-block: var(--a26-s-3);
  padding-inline: var(--a26-s-3) var(--a26-s-2);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-step-head {
    gap: var(--a26-s-4);
    padding-block: var(--a26-s-4);
    padding-inline: var(--a26-s-4) var(--a26-s-2);
  }
}
html[data-brand="aktiv-2026"] .a26h-step-head::-webkit-details-marker {
  display: none;
}
html[data-brand="aktiv-2026"] .a26h-step-head:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: -2px;
}
html[data-brand="aktiv-2026"] .a26h-step-num {
  flex-shrink: 0;
}
html[data-brand="aktiv-2026"] .a26h-step-title {
  flex-grow: 1;
  min-width: 0;
}
/* The chevron sits hard right (x=1386 of 1440 on LTK-0, x=393 of 428 on
   LTL-0) and flips when the row is open. */
html[data-brand="aktiv-2026"] .a26h-step-chev {
  align-self: center;
  color: var(--a26-ink-chrome);
  display: block;
  flex-shrink: 0;
  height: 11px;
  transition: transform var(--dur-a26-chrome) var(--ease-a26-micro);
  width: 9px;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-step-chev {
    height: 15px;
    width: 13px;
  }
}
html[data-brand="aktiv-2026"] .a26h-step[open] .a26h-step-chev {
  transform: rotate(180deg);
}
/* The row head is a control: its title goes to ink-fill on hover the way a
   control does? No — it is a disclosure line, not a button; the boards draw
   it as text. It gets the text-link hover: the title underlines. */
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-step-head:hover .a26h-step-title {
    text-decoration: underline;
    text-decoration-thickness: var(--a26-hairline-w);
    text-underline-offset: 0.14em;
  }
}
html[data-brand="aktiv-2026"] .a26h-step-body {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-5);
  padding-bottom: var(--a26-s-6);
  padding-top: var(--a26-s-1);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-step-body {
    gap: var(--a26-s-6);
    padding-bottom: var(--a26-s-7);
  }
}
html[data-brand="aktiv-2026"] .a26h-step-visual {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-5);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-step-visual {
    gap: var(--a26-s-6);
  }
}
/* LTK-0's open row runs the video 583 wide inside the 912 column; LTL-0 runs
   it full width. */
html[data-brand="aktiv-2026"] .a26h-step-media {
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-step-media {
    max-width: var(--a26-media-w);
  }
}

/* ---- The two panels: white, 1px ink, square. ----------------------------
   One panel device for the caption suggestion and the composer mock. */
html[data-brand="aktiv-2026"] .a26h-panel {
  background-color: var(--a26-white);
  border: var(--a26-hairline-w) solid var(--a26-ink-chrome);
  border-radius: var(--a26-radius-card);
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
  padding: var(--a26-s-5);
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-panel {
    gap: var(--a26-s-5);
    max-width: var(--a26-media-w);
  }
}
/* The panel's label: mono, uppercase, chrome ink — not muted. */
html[data-brand="aktiv-2026"] .a26h-panel-label {
  color: var(--a26-ink-chrome);
}
html[data-brand="aktiv-2026"] .a26h-caption {
  color: var(--a26-body);
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-body);
  font-weight: 400 !important;
  line-height: var(--a26-lh-body);
  white-space: pre-wrap;
}

/* ---- The composer mock (row 2 of the Facebook steps) --------------------
   A static picture of the Facebook composer, modelled on the aktiv-2019
   hub's mock (rev 1.1 §6.5): header (avatar, the seller's name, audience),
   the empty prompt line, a dashed DROP ZONE with the promo's filename
   arriving as a dragged file tag, and the app's foot: "Foto/video" and its
   "Publiser". Drawn in the panel device with the app's proportions. It is
   an ILLUSTRATION: aria-hidden, no pointer, nothing in it can be pressed,
   and its "Publiser" is deliberately NOT the page's button device — no ink
   fill, no 48 height, low contrast, default cursor — so that a reader never
   takes it for the thing to press (Henrik, 2026-09-06). None of it spends
   orange. */
html[data-brand="aktiv-2026"] .a26h-composer {
  cursor: default;
  gap: 0;
  padding: 0;
  pointer-events: none;
  user-select: none;
}
html[data-brand="aktiv-2026"] .a26h-composer-head {
  align-items: center;
  display: flex;
  gap: var(--a26-s-3);
  padding: var(--a26-s-4) var(--a26-s-5) var(--a26-s-3);
}
html[data-brand="aktiv-2026"] .a26h-composer-name {
  line-height: var(--a26-lh-ui);
}
/* Round on purpose: this is the mocked composer and the disc is part of what
   makes it read as the social app rather than as an a26 control.

   LADDER EXCEPTION, DELIBERATE (type coherence audit 2026-09-05 §2, exception
   a). The initials are set in Varighet at the ui SIZE — a pairing the ladder
   does not otherwise allow, since Varighet stops at h3. It is legal here for
   the same reason the disc is round: everything inside .a26h-composer is a
   picture OF ANOTHER APP, aria-hidden and pointer-events: none, not page type.
   The size is still a ladder token, so it can never drift off the scale. */
html[data-brand="aktiv-2026"] .a26h-avatar {
  align-items: center;
  background-color: var(--a26-peach);
  border-radius: 50%;
  color: var(--a26-text);
  display: flex;
  flex-shrink: 0;
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-ui);
  height: var(--a26-s-7);
  justify-content: center;
  line-height: 1;
  width: var(--a26-s-7);
}
html[data-brand="aktiv-2026"] .a26h-composer-prompt {
  color: var(--a26-muted);
  padding: 0 var(--a26-s-5) var(--a26-s-4);
}
/* The drop zone: the app's dashed target on the canvas tint, its upload
   arrow, "Slipp videoen her" in ui and the alternative in muted mono. Inset
   by the panel's padding on both sides; the file tag hangs over its left
   edge. */
html[data-brand="aktiv-2026"] .a26h-composer-drop {
  align-items: center;
  background-color: var(--a26-canvas);
  border: var(--a26-hairline-w) dashed var(--a26-ink-chrome);
  color: var(--a26-ink-chrome);
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-2);
  margin: 0 var(--a26-s-5);
  padding: var(--a26-s-7) var(--a26-s-5);
  position: relative;
  text-align: center;
}
html[data-brand="aktiv-2026"] .a26h-composer-drop > svg {
  height: var(--a26-s-6);
  margin-bottom: var(--a26-s-1);
  width: var(--a26-s-6);
}
html[data-brand="aktiv-2026"] .a26h-composer-drop-title {
  line-height: var(--a26-lh-ui);
}
/* The dragged file: an ink tag with the filename in canvas mono, straddling
   the drop zone's top-left corner and tilted a few degrees so it reads as a
   file in motion (the aktiv-2019 mock's device). It hangs above the arrow,
   never over it. A static transform, never transitioned. */
html[data-brand="aktiv-2026"] .a26h-composer-tag {
  background-color: var(--a26-ink-chrome);
  border-radius: var(--a26-radius-control);
  left: calc(-1 * var(--a26-s-3));
  max-width: calc(100% - var(--a26-s-5));
  padding: var(--a26-s-3) var(--a26-s-4);
  position: absolute;
  top: calc(-1 * var(--a26-s-3));
  transform: rotate(-3deg);
}
html[data-brand="aktiv-2026"] .a26h-composer-tag > .a26h-mono {
  color: var(--a26-canvas);
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: none;
  white-space: nowrap;
}
/* The app's foot: "Foto/video" left, its publish label right. */
html[data-brand="aktiv-2026"] .a26h-composer-foot {
  align-items: center;
  border-top: var(--a26-hairline-w) solid var(--a26-hairline-soft);
  display: flex;
  gap: var(--a26-s-3);
  justify-content: space-between;
  margin-top: var(--a26-s-5);
  padding: var(--a26-s-4) var(--a26-s-5) var(--a26-s-5);
}
html[data-brand="aktiv-2026"] .a26h-composer-add {
  color: var(--a26-muted);
  line-height: var(--a26-lh-ui);
}
/* The mocked publish label. Reduced contrast on purpose: a soft hairline on
   the canvas tint with muted text, a shallower box than any real control —
   it is the app's control seen from a distance, not one of ours. It must
   never read as something to press on THIS page. */
html[data-brand="aktiv-2026"] .a26h-mockbtn {
  background-color: var(--a26-canvas);
  border: var(--a26-hairline-w) solid var(--a26-hairline-soft);
  border-radius: var(--a26-radius-control);
  color: var(--a26-muted);
  cursor: default;
  display: inline-flex;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  line-height: var(--a26-lh-ui);
  opacity: 0.7;
  padding: var(--a26-s-2) var(--a26-s-5);
}

/* ============================================================================
   07 — SECTION INTRO (LTK-0 M7P-0 · LTL-0 MM2-0)

   Eyebrow + headline + body, text only. The boards stack three of these in
   07 and the cards follow in 08; since the 2026-09-05 graphics device and
   its 2026-09-06 revision there are TWO such intros ("Grafikk for visning"
   and "Nøkkelinfo", the aktiv-2019 hub's order) and each one's device
   follows it directly, so the copy sits beside what it introduces.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-band {
  padding-block: var(--a26-band) var(--a26-band-end);
}
html[data-brand="aktiv-2026"] .a26h-intro {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
}
@media (min-width: 1024px) {
  /* A text block has no row head to carry the 16px the accordion's does, so it
     takes it back here and its headline lands on the boards' 32. */
  html[data-brand="aktiv-2026"] .a26h-intro,
  html[data-brand="aktiv-2026"] .a26h-bulk {
    padding-top: var(--a26-s-2);
  }
  html[data-brand="aktiv-2026"] .a26h-intro {
    gap: var(--a26-s-5);
  }
}
/* What an intro block introduces, when it has anything — the device. */
html[data-brand="aktiv-2026"] .a26h-introbelow {
  padding-top: var(--a26-s-6);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-introbelow {
    padding-top: var(--a26-s-7);
  }
}

/* ============================================================================
   08 — THE GRAPHICS-DELIVERY DEVICE
   (docs/design/2026-09-05-a26-graphics-delivery-device.md §2; Paper boards
   VAU-0 / VDF-0 / VDG-0 / VDH-0 / VDI-0 on D-0)

   One device per graphics section (rev 1.1, §6 of the spec), top to bottom:
   the set strip (showings only, and only when there is more than one), the
   frame whose TOP EDGE is the format toggle, the fixed-height stage, Del
   (orange) + Last ned directly under the stage in the frame's column, then
   the mono spec line and the caption as the outlined suggestion panel
   (.a26h-panel: label, caption, Kopier teksten). Desktop: frame + actions
   left, spec line + panel right.

   Every rule here resolves through the ladders: the segment is the control
   height (48) in the ui rung, the frame and every divider is the hairline in
   ink-chrome — ONE ink on one device (deviation 1 in the spec: not the cards'
   #000), the stage is an `aspect-ratio` box with `--a26-stage-pad` of air.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-device {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-3);
}
html[data-brand="aktiv-2026"] .a26h-device-visual {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-3);
  min-width: 0;
}
html[data-brand="aktiv-2026"] .a26h-device-text {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
  min-width: 0;
}
@media (min-width: 1024px) {
  /* Two columns inside the 912 content column: frame 440 · 32 · text 440.
     Between 1024 and 1180 the rail leaves the content column narrower than
     912; the two columns shrink evenly rather than overflow the page (the
     spec's "the page grid carries the squeeze", read as: never a horizontal
     scrollbar — deviation logged). */
  html[data-brand="aktiv-2026"] .a26h-device {
    align-items: start;
    column-gap: var(--a26-s-6);
    display: grid;
    grid-template-columns: repeat(2, minmax(0, var(--a26-device-col)));
  }
}

/* ---- The segmented control: the format toggle and the set strip ---------
   Even segments, each the control height in the ui rung, 1px ink dividers
   between them; the strip carries its own 1px outline, the toggle borrows
   the frame's and closes with the rule below it. Selected = ink fill, canvas
   label (the chips rule: dark, never orange). No sliding indicator — a switch
   is a 200ms colour swap and nothing moves (spec §2.8). */
html[data-brand="aktiv-2026"] .a26h-seg {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
html[data-brand="aktiv-2026"] .a26h-seg--sets {
  border: var(--a26-hairline-w) solid var(--a26-ink-chrome);
}
html[data-brand="aktiv-2026"] .a26h-seg--formats {
  border-bottom: var(--a26-hairline-w) solid var(--a26-ink-chrome);
}
html[data-brand="aktiv-2026"] .a26h-seg-item {
  appearance: none;
  background-color: transparent;
  border: 0;
  border-left: var(--a26-hairline-w) solid var(--a26-ink-chrome);
  border-radius: var(--a26-radius-control);
  color: var(--a26-ink-chrome);
  cursor: pointer;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  font-weight: 400 !important;
  line-height: var(--a26-lh-ui);
  margin: 0;
  min-height: var(--a26-control-h);
  min-width: 0;
  overflow: hidden;
  padding-block: 0;
  padding-inline: var(--a26-s-2);
  position: relative;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition:
    background-color var(--dur-micro) var(--ease-a26-micro),
    color var(--dur-micro) var(--ease-a26-micro),
    transform var(--dur-micro) var(--ease-a26-micro);
}
html[data-brand="aktiv-2026"] .a26h-seg-item:first-child {
  border-left: 0;
}
/* Four or more showings: the strip wraps to rows of two or three even
   segments; the first segment of each row has no left divider and rows two
   and up gain a top rule (spec §2.6). */
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="2"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="3"] {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="2"] > .a26h-seg-item:nth-child(2n + 1),
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="3"] > .a26h-seg-item:nth-child(3n + 1) {
  border-left: 0;
}
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="2"] > .a26h-seg-item:nth-child(n + 3),
html[data-brand="aktiv-2026"] .a26h-seg[data-a26-cols="3"] > .a26h-seg-item:nth-child(n + 4) {
  border-top: var(--a26-hairline-w) solid var(--a26-ink-chrome);
}
html[data-brand="aktiv-2026"] .a26h-seg-item[aria-checked="true"] {
  background-color: var(--a26-ink-chrome);
  color: var(--a26-canvas);
}
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-seg-item:hover {
    background-color: var(--a26-hover-fill);
    color: var(--a26-hover-text);
  }
}
html[data-brand="aktiv-2026"] .a26h-seg-item:active {
  transform: scale(var(--a26-press-scale));
}
html[data-brand="aktiv-2026"] .a26h-seg-item:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: 2px;
  z-index: 1;
}
/* On the ink-filled selected segment the ink ring would vanish — it is drawn
   in canvas, inside the segment. */
html[data-brand="aktiv-2026"] .a26h-seg-item[aria-checked="true"]:focus-visible {
  outline-color: var(--a26-canvas);
  outline-offset: calc(-1 * var(--a26-s-1));
}

/* ---- The frame and the stage --------------------------------------------- */
html[data-brand="aktiv-2026"] .a26h-devframe {
  background-color: var(--a26-white);
  border: var(--a26-hairline-w) solid var(--a26-ink-chrome);
  border-radius: var(--a26-radius-card);
}
/* THE STAGE FOLLOWS THE FORMAT (rev 1.3, Henrik 2026-09-12).
   Equal air on all four sides, the graphic filling the frame's content width,
   and the box height whatever that width implies at the chosen format's
   aspect. The mechanism is `box-sizing: content-box` + `aspect-ratio`: per CSS
   Sizing 4 the ratio applies to the box named by `box-sizing`, so it lands on
   the CONTENT box and the padding is added outside it. The content box is
   therefore exactly the graphic — width = frame content width - 2x pad, height
   = that width at the format's ratio — and the stage box is the graphic plus
   one pad on every side. Nothing is derived from a board literal, so the
   geometry holds through the 1024-1180 squeeze where the device columns shrink
   below 440.
   The layers stay absolutely positioned and keep `inset: var(--a26-stage-pad)`
   unchanged: an absolutely positioned child is laid out against its container's
   PADDING box, so insetting by one pad lands it precisely on the content box.
   NOTE THE TRANSITION LIST — opacity only, on the layers, never here.
   `aspect-ratio` is deliberately not transitionable in this sheet: the box
   SNAPS to the new format and the 200 ms crossfade plays on top of it. A
   height tween would be the one motion this system does not do (spec §2.8 and
   the motion rule: no height tweens). */
html[data-brand="aktiv-2026"] .a26h-stage {
  box-sizing: content-box;
  overflow: hidden;
  padding: var(--a26-stage-pad);
  position: relative;
}
/* The three ratios, written width/height so they read as the format does.
   The modifier and the base class travel in ONE string literal in
   GraphicsDevice — see its note on the gate proof's 14-character window. */
html[data-brand="aktiv-2026"] .a26h-stage--feed {
  aspect-ratio: 4 / 5;
}
html[data-brand="aktiv-2026"] .a26h-stage--story {
  aspect-ratio: 9 / 16;
}
html[data-brand="aktiv-2026"] .a26h-stage--bredformat {
  aspect-ratio: 3 / 2;
}
/* Every graphic the reader has opened is its own layer, stacked in the
   stage's padding box; exactly one is on. A switch is opacity only — the
   crossfade of spec §2.8 — and the off layers are inert (no pointer, no tab
   stop, no accessibility node). */
html[data-brand="aktiv-2026"] .a26h-stage-layer {
  inset: var(--a26-stage-pad);
  opacity: 0;
  pointer-events: none;
  position: absolute;
  transition: opacity var(--dur-micro) var(--ease-a26-micro);
}
html[data-brand="aktiv-2026"] .a26h-stage-layer[data-a26-on] {
  opacity: 1;
  pointer-events: auto;
}
html[data-brand="aktiv-2026"] .a26h-stage-graphic {
  appearance: none;
  background-color: transparent;
  border: 0;
  border-radius: var(--a26-radius-card);
  display: block;
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}
html[data-brand="aktiv-2026"] .a26h-stage-graphic:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: 2px;
}
html[data-brand="aktiv-2026"] .a26h-stage-graphic > img {
  display: block;
  height: 100%;
  object-fit: contain;
  transition: transform var(--dur-a26-chrome) var(--ease-a26-micro);
  width: 100%;
}
/* The hub gallery rule: the graphic 1.0 -> 1.02 under the pointer. */
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-stage:hover .a26h-stage-layer[data-a26-on] .a26h-stage-graphic > img {
    transform: scale(1.02);
  }
}

/* ---- Under the frame ------------------------------------------------------ */
html[data-brand="aktiv-2026"] .a26h-device-spec {
  color: var(--a26-ink-chrome);
}
/* The actions row under the stage keeps the phone gap at every width: Del ·
   Last ned share one row at 12 apart on both viewports. */
html[data-brand="aktiv-2026"] .a26h-device .a26h-actions {
  gap: var(--a26-s-3);
}
/* The suggestion panel fills the text column (the panel's desktop max-width
   is wider than the column, so it never binds here). */
html[data-brand="aktiv-2026"] .a26h-device-panel {
  max-width: none;
}
/* A device carrying `.a26h-device--nocaption-phone` drops its suggestion panel
   BELOW 1024 (rev 1.2, Henrik 2026-09-12). On a phone the same caption was
   printed four times down one scroll — Facebook step 3, Instagram step 3 and
   both graphics devices — so the Nøkkelinfo device gives its copy up and the
   reader takes the text from the showing device or from the accordion step
   that asks for it. The panel's own `Kopier teksten` goes with the panel; what
   is left of that device on a phone is the stage, Del · Last ned and the mono
   spec line. DESKTOP IS UNTOUCHED: all four panels stand at 1024 and up, so
   this is one rule at one width and not a second component.
   (The marker is a class rather than a `data-a26-…` attribute for a reason
   the gate proof taught this round — see GraphicsDevice's own note.) */
@media (max-width: 1023px) {
  html[data-brand="aktiv-2026"] .a26h-device--nocaption-phone .a26h-device-panel {
    display: none;
  }
}

/* THE TABLET CAP (round 10, 2026-09-13). Between 768 and 1023 the device is
   still the phone's single column, but the column is now up to 1023 wide — so
   a full-width Innlegg stage stood about 888 px tall and one graphic filled
   the screen. The desktop grid already knows the right width for this device:
   `--a26-device-col`, the 440 board. So the VISUAL COLUMN takes that as a cap
   on the tablet band and centres in the column; the text column below it keeps
   the full measure, which is what a paragraph wants.

   It is `.a26h-device-visual`, not `.a26h-devframe`, on purpose: the set strip
   and the Del · Last ned row are part of the frame's own column (rev 1.1 —
   "the verbs sit under the graphic they act on"), and capping the frame alone
   would leave them running the full width under a 440 stage.

   Phones and 1024-and-up are untouched: below 768 the full-width stage is the
   whole point of a phone layout, and at 1024 the two-column grid takes over
   and already binds each column to the same token. */
@media (min-width: 768px) and (max-width: 1023px) {
  html[data-brand="aktiv-2026"] .a26h-device-visual {
    margin-inline: auto;
    max-width: var(--a26-device-col);
    /* `width: 100%` IS LOAD-BEARING, and the reason is a flexbox rule that is
       easy to walk into: the device is a column flex container, so this column
       is a flex ITEM stretched on the cross axis — and `align-self: stretch`
       does not apply to an item with an auto cross-axis margin. Adding
       `margin-inline: auto` alone therefore dropped the stretch and shrank the
       column to fit-content, i.e. to the natural width of the Del · Last ned
       row: measured 228.28 px at both 768 and 834, a quarter of the column.
       A definite `width` restores the size; `max-width` then caps it and the
       auto margins centre what is left. */
    width: 100%;
  }
}

/* ---- The graphic's lightbox: the corner «Del» -----------------------------
   Henrik, 2026-09-13, on his phone: «im seeing the sharebutton is orange when
   in the lightbox, which is nice. lets have that propagate to the other
   lightbox previews as well. when they are in the lightbox preview of
   graphics, they should have a button in the corner that is orange. make sure
   its uniform across the sharehubs.»

   The lightbox itself is the SHARED component (components/boligpromo/
   ImageLightbox.tsx), which the aktiv-2019 cards also open; it gained an
   optional `footer` that defaults to undefined, and the a26 tree composes this
   corner box into it. So the control is the hub's OWN «Del» — the same
   `.a26h-pill.a26h-pill--cta` device as the one under the stage, the same
   orange, the same ink, the same two-phase share — rather than a second share
   button with its own geometry.

   THE BOX LANDS 88 x 48, WHICH IS THE HUB'S CONTROL, not the sharehubs' legacy
   85 x 40. The visning notes' lightbox contract records those two numbers as
   the EXISTING reading rather than the intended one ("the box is 40 px tall,
   not 44" — under the tap floor), so matching this hub's 48px control device
   both clears `--a26-tap` without an overlay and keeps the page to one button
   size. The inset is the contract's: 20 right, 17 bottom.

   The lightbox is portaled to document.body, outside `.a26h` — which is why
   this rule hangs off `html[data-brand]` like every other in the sheet and
   needs nothing from the hub root.

   COLUMN-REVERSE is load-bearing: A26ShareButton renders its progress line,
   its did-not-land notice and its fallback trigger as SIBLINGS after the
   button, and in a bottom-anchored corner they would otherwise be laid out off
   the bottom of the viewport. Reversed, the button stays in the corner and
   anything it raises stacks upward into the picture. */
html[data-brand="aktiv-2026"] .a26h-lbdel {
  align-items: flex-end;
  bottom: 17px;
  display: flex;
  flex-direction: column-reverse;
  gap: var(--a26-s-2);
  position: absolute;
  right: 20px;
  z-index: 1;
}

/* ============================================================================
   09 — BULK DOWNLOAD (LTK-0 MY2-0 · LTL-0 N11-0)

   Eyebrow, headline, mono breakdown, body, one orange control — on the plain
   canvas. (GS6-0's dark finale band is gone; neither agency board draws one.)
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-bulk {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
}
html[data-brand="aktiv-2026"] .a26h-bulk-cta {
  display: inline-flex;
  padding-top: var(--a26-s-5);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-bulk-cta {
    padding-top: var(--a26-s-6);
  }
}

/* ============================================================================
   10 — FOOTER (LTK-0 MAO-0 · LTL-0 MUF-0)

   The agency's own site footer: monogram lockup, three large arrowed links,
   a secondary link column and a legal line. LTK-0: the lockup 118x100 at the
   left gutter, the arrowed lines from x=730 (text from 774) in h1 at 56/70,
   the secondary column from x=1192 at 16/22, the legal line at y=351 at
   12/15; the section is 400 tall. LTL-0 stacks everything at x=20: lockup,
   54 of air, the three lines at 32/43, 18 of air, the six links, 45 of air,
   the legal line.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-footer {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-7);
  padding-block: var(--a26-s-3) var(--a26-s-5);
  padding-inline: var(--a26-gutter);
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer {
    /* LTK-0: lockup at the gutter, the arrowed lines from x=730, the secondary
       column from x=1192. Columns, not gaps — a column gap here would push
       both of those right and squeeze the third track. Fractions of the 1376
       content width so it holds between 1024 and 1440. */
    column-gap: 0;
    display: grid;
    grid-template-columns: minmax(0, 50.73%) minmax(0, 33.58%) minmax(0, 1fr);
    padding-block: 0 var(--a26-s-6);
    row-gap: var(--a26-s-9);
  }
}
/* The monogram, at the boards' footprint: 84x72 on LTL-0, 118x100 on LTK-0.
   An inline <svg> (see A26Footer), so it takes its colour from `fill`. */
html[data-brand="aktiv-2026"] .a26h-footer-mark {
  color: var(--a26-ink-chrome);
  display: block;
  height: 72px;
  width: 84px;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer-mark {
    height: 100px;
    width: 118px;
  }
}
html[data-brand="aktiv-2026"] .a26h-footer-nav {
  display: flex;
  flex-direction: column;
  gap: 0;
}
/* Below 1024 the footer stacks (see the grid rule above) and the three
   columns are no longer siblings in one row, so nothing here needs pulling
   up to a shared top. At and above 1024 the mark, the nav and the secondary
   links column all start in grid row 1 — box-top aligned by the grid alone —
   but the mark is an SVG with no font leading while the nav (h1/lh-nav rung)
   and the links (ui rung) each carry their own half-leading gap above the
   cap line, so their BOX tops land well below the mark's VISUAL top. Pulled
   up by the rung's own measured trim (2026-09-15 alignment pass) so all
   three share one cap-top / visual top. */
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer-nav {
    margin-top: var(--a26-ink-trim-nav);
  }
}
/* The three lines: h1 (32 mobile, fluid 40-56 desktop) with the nav's own
   looser leading (43 / 70 on the boards). */
html[data-brand="aktiv-2026"] .a26h-footer-navitem {
  align-items: center;
  color: var(--a26-ink-chrome);
  display: flex;
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h1);
  font-weight: 400 !important;
  gap: var(--a26-s-4);
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-nav);
}
/* The navigation lines and the secondary column are real links (their
   destinations arrive from the Chain Manifest, never as literals). Plain
   text links: ink at rest, no underline, as both boards draw them; hover
   keeps the ink and underlines. */
html[data-brand="aktiv-2026"] .a26h-footer-navitem a,
/* The legal row joins these: one part of that sentence (the visitor-statistics
   note) is a link, and it should read as the rest of the row until it is
   hovered or focused — the row's own muted ink, no underline at rest. The
   60% -opacity blend this comment used to name is gone with the row's
   own-recipe colour (see the legal-row rule below). */
html[data-brand="aktiv-2026"] .a26h-footer-links a,
html[data-brand="aktiv-2026"] .a26h-footer-legal a {
  color: inherit;
  text-decoration: none;
}
@media (hover: hover) {
  html[data-brand="aktiv-2026"] .a26h-footer-navitem a:hover,
  html[data-brand="aktiv-2026"] .a26h-footer-links a:hover,
  html[data-brand="aktiv-2026"] .a26h-footer-legal a:hover {
    text-decoration: underline;
    text-decoration-thickness: var(--a26-hairline-w);
    text-underline-offset: 0.14em;
  }
}
html[data-brand="aktiv-2026"] .a26h-footer-navitem a:focus-visible,
html[data-brand="aktiv-2026"] .a26h-footer-links a:focus-visible,
html[data-brand="aktiv-2026"] .a26h-footer-legal a:focus-visible {
  outline: 2px solid var(--a26-ink-chrome);
  outline-offset: 3px;
}
html[data-brand="aktiv-2026"] .a26h-footer-arrow {
  flex-shrink: 0;
  height: 12px;
  width: 15px;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer-arrow {
    height: 22px;
    width: 27px;
  }
}
html[data-brand="aktiv-2026"] .a26h-footer-links {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-1);
}
/* Shares one cap-top with the mark and the nav column — see the trim note on
   .a26h-footer-nav above; this column's own rung is .a26h-ui, not the nav's
   h1, so it gets its own measured amount. */
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer-links {
    margin-top: var(--a26-ink-trim-ui);
  }
}
/* ONE LINE, not three (Henrik, 2026-09-11: "the copyright, besøksstatistikk
   and personvern is crammed together over three lines. should be one").

   TWO THINGS WERE MAKING IT THREE, and both had to go:
     1. The row was a wrapping FLEX of block spans with a 32/96 column gap, so
        every part was its own flex item and a 96px gap between them.
     2. It spanned grid COLUMNS 2-3 — 473px of the 960 content box at 1024 and
        671 of 1361 at 1440 — and the sentence measures ~711px in the mono
        rung. It could not fit however it was laid out.
   So it is now normal inline flow inside a <p> (the separators are real text,
   from A26Footer) spanning the WHOLE grid, `1 / -1`. LEFT at the gutter, not
   flush right: the hub's footer is a left-rail grid — monogram, nav and the
   secondary column all start at their column's left edge — and there is no
   flush-right column here to echo (the visning footer's right alignment comes
   from its own body column, which this footer does not have). Measured at
   1024/1180/1440: one line at all three, with 249/326/650 px to spare.

   TYPOGRAPHY IS THE VISNING ROW'S, verbatim (the reference footer contract):
   the mono rung at 12 with the mono-TEXT leading 16 rather than the 15 the
   label rung uses, sentence case, `--a26-muted` ink. That last one replaces an
   ink-chrome-at-0.6-opacity deviation this row used to carry alone; the two
   compute within four levels of each other (the old blend was #736963 against
   this #6F655D) and the token is what every other muted line on both surfaces
   already reads, so the row stops being the one place with its own recipe. It
   is also very slightly BETTER: measured on the footer canvas #FAF5F0,
   5.25:1 against the old blend's 4.94:1 — AA either way. */
html[data-brand="aktiv-2026"] .a26h-footer-legal {
  color: var(--a26-muted);
  font-family: var(--font-a26-mono) !important;
  font-size: var(--a26-t-mono);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-mono);
  line-height: var(--a26-lh-mono-text);
  margin: 0;
}
/* The row is a SENTENCE and stays sentence-case — the mono rung's own caps
   would read as chrome. The copyright HOLDER is the exception: a brand name,
   which the board sets in caps. This is why the row no longer carries
   `.a26h-mono` (that class shouts, and it shouted all three lines): the holder
   is the only part that should, and the caller declares it with `caps`. */
html[data-brand="aktiv-2026"] .a26h-footer-legal .a26h-footer-holder {
  text-transform: uppercase;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-footer-legal {
    grid-column: 1 / -1;
  }
}

/* ============================================================================
   THE CLOSING BLOCK — not on either board, NOT RENDERED since 2026-09-05
   (Henrik: hide for now; the component is kept). Rules kept so the block
   comes back in the ladder if it is switched on again.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-signoff {
  display: flex;
  flex-direction: column;
  gap: var(--a26-s-4);
  max-width: var(--a26-measure);
}
html[data-brand="aktiv-2026"] .a26h-signoff-line {
  color: var(--a26-ink-chrome);
  font-family: var(--font-a26-display) !important;
  font-size: var(--a26-t-h3);
  font-weight: 400 !important;
  letter-spacing: var(--a26-track-display);
  line-height: var(--a26-lh-h3);
}
html[data-brand="aktiv-2026"] .a26h-signoff .a26h-contactpair {
  margin-top: var(--a26-s-1);
}

/* ============================================================================
   MOTION

   MECHANISM. The hub already ships a brand-agnostic IntersectionObserver
   (components/boligpromo/RevealObserver.tsx — a SHARED file, deliberately not
   edited) that adds `.bp-revealed` once to anything carrying `.bp-fade-up`,
   and reveals everything instantly under prefers-reduced-motion. The a26
   variants ride on it: the same element also carries
   `data-a26-reveal="<variant>"`. The observer sees the class; this stylesheet
   reads the attribute. No second observer, no reveal JS — and no motion JS AT
   ALL, because neither agency board implies a sticky bar.

   DELAYS. The a26 tree carries an inline `--a26-delay` custom property rather
   than the observer's `data-bp-delay`. Custom properties inherit, so one value
   on a group's wrapper reaches every part of a compound reveal and each offset
   can be written as `calc(var(--a26-delay, 0ms) + <token>)`.

   CLIPPING. Compound variants put the reveal class on an UNCLIPPED wrapper and
   drive their children from that wrapper's `.bp-revealed`: an
   IntersectionObserver measures intersection AFTER ancestor clipping, so a
   child translated fully out of an `overflow: hidden` parent never reports as
   intersecting and would hang at its start state forever.

   BUDGET. transform + opacity only — no layout property is animated below, and
   no rule carries a `cubic-bezier(` or a bare `ms`: every duration, easing and
   offset resolves through the tokens at the top of this file.
   ============================================================================ */

/* ---- Base reveal: opacity + a 16px rise --------------------------------- */
html[data-brand="aktiv-2026"].js-reveal .bp-fade-up {
  transform: translateY(var(--a26-s-4));
  transition:
    opacity var(--a26-fade, var(--dur-reveal)) var(--ease-a26),
    transform var(--a26-fade, var(--dur-reveal)) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}
/* The a26 base rule above outranks globals.css's
   `.js-reveal .bp-fade-up.bp-revealed` (0,3,1 vs 0,2,0), so the landed state
   has to be restated at a26 strength or nothing would ever arrive. */
html[data-brand="aktiv-2026"].js-reveal .bp-fade-up.bp-revealed {
  opacity: 1;
  transform: translateY(0);
}
html[data-brand="aktiv-2026"].js-reveal .bp-line-trim {
  transition: transform var(--dur-a26-draw) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}

/* ---- eyebrow / eyebrow-load ---------------------------------------------
   The section opener. The agency boards draw no rule beside the label, so the
   rule element is zero-width and the visible move is the label's arrival. */
html[data-brand="aktiv-2026"] [data-a26-reveal^="eyebrow"] {
  --a26-draw: var(--dur-a26-draw);
  --a26-gap: var(--delay-a26-eyebrow);
}
html[data-brand="aktiv-2026"] [data-a26-reveal="eyebrow-load"] {
  --a26-draw: var(--dur-a26-draw-load);
  --a26-gap: var(--delay-a26-eyebrow-load);
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="eyebrow"] {
  opacity: 1;
  transform: none;
  transition: none;
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="eyebrow"] .a26h-eyebrow-rule {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--a26-draw) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="eyebrow"].bp-revealed .a26h-eyebrow-rule {
  transform: scaleX(1);
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="eyebrow"] .a26h-mono--eyebrow {
  opacity: 0;
  transform: translateY(var(--a26-s-2));
  transition:
    opacity var(--a26-draw) var(--ease-a26),
    transform var(--a26-draw) var(--ease-a26);
  transition-delay: calc(calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1)) + var(--a26-gap));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="eyebrow"].bp-revealed .a26h-mono--eyebrow {
  opacity: 1;
  transform: translateY(0);
}

/* ---- title / title-hero -------------------------------------------------
   THE SIGNATURE MOVE: display type rises out of a baseline clip mask. The text
   is real text in the server HTML and paints immediately — only its transform
   animates, inside the mask. At hero size it runs on `--dur-hero`; at section
   size the same shape runs on `--dur-reveal`. */
/*
 * ---- THE MASK'S HEADROOM (round 9) ---------------------------------------
 *
 * Henrik, 2026-09-13: «in the bårdsund 10 site, im seeing the Å is cut off on
 * top a bit. that should be fixed, and also potentially some lower potential
 * cut offs with j or y or similar.»
 *
 * He is right, and the numbers say by how much. Ink bounds (canvas
 * `actualBoundingBox*` on the string AS RENDERED — uppercased, because these
 * lines are `text-transform: uppercase` and a lowercase «å» is a ring on an
 * x-height letter while «Å» is a ring above the CAP) against this wrapper's
 * clip box, `a26-demo-bardsund-10`, room to the edge in px:
 *
 *                          428          1440
 *   over the Å            -1.52        -3.30
 *   under j y g p         -1.73        -6.73
 *
 * The cause is the rung, not the face: `--a26-lh-display` is **1**, so the
 * display line box IS the em box, and every part of the ink that lives outside
 * the em box — the ring over the Å, the tail of a j — falls outside the clip.
 * Every other masked rung has leading to spare (h1 35.52/32, h2 32/28,
 * h3 28/24) and measured positive at both widths; the headroom is given to the
 * DEVICE anyway, because the defect belongs to the wrapper and the next rung
 * set on a 1.0 leading would reintroduce it in silence.
 *
 * THE FIX IS THE WRAPPER'S, NOT THE TYPE'S — and it does not touch layout at
 * all. `clip-path` is a PAINT operation: an outward inset moves where the box
 * is cut without moving the box, so not one rect on the page changes. The
 * padding-plus-negative-margin construction was built and measured first and
 * rejected on exactly that point: it is layout-neutral in arithmetic but not
 * in LayoutUnit, and it drifted 2124 rendered boxes by up to 0.07 px.
 *
 * WHY THE HEADROOM IS KEYED TO THE RUNG AND NOT WRITTEN IN `em`. This wrapper
 * is a plain <div>; its own font-size is the inherited 16 px at BOTH widths
 * (measured), so the `0.08em` this rule carries is 1.28 px under a 100 px
 * display line — which is exactly why the descenders were cut. The headroom
 * therefore reads the rung's own token through `:has()`. 0.12 / 0.16 of the
 * rung clears the worst measured extent (0.038 and 0.067 of the rung) with
 * better than 2x margin at every rung and at both widths.
 *
 * AND THE RISE STILL STARTS OUT OF SIGHT. The bottom edge of this box is the
 * only thing hiding the un-risen line, so moving the cut down by
 * `--a26-mask-foot` would show the tops of the glyphs before the reveal. The
 * child's start offset is therefore 110 % PLUS the same token, which puts it
 * at exactly the same distance below the visible edge as before: the rise
 * looks identical and the pre-reveal state stays empty. The token is built
 * from `--a26-t-*`, never from `em`, because a custom property's `em` resolves
 * against the element that USES it — and the user of this one is the child,
 * whose font-size is the rung.
 *
 * THE FALLBACK IS TODAY'S RULE, UNCHANGED. Where `clip-path: inset()` is not
 * supported the base rule below stands on its own — `overflow: hidden` and the
 * 0.08em foot — and `--a26-mask-foot` is never defined, so the child's
 * `var(..., 0px)` leaves the rise exactly where it is. The device degrades to
 * the clipping it has today, never to an unclipped line.
 */
html[data-brand="aktiv-2026"] .a26h-mask {
  /* The rung the masked line is set on. Overridden per rung just below. */
  --a26-mask-rung: 1rem;
  overflow: hidden;
  padding-bottom: 0.08em;
}
html[data-brand="aktiv-2026"] .a26h-mask:has(> .a26h-display) {
  --a26-mask-rung: var(--a26-t-display);
}
html[data-brand="aktiv-2026"] .a26h-mask:has(> .a26h-h1) {
  --a26-mask-rung: var(--a26-t-h1);
}
html[data-brand="aktiv-2026"] .a26h-mask:has(> .a26h-h2) {
  --a26-mask-rung: var(--a26-t-h2);
}
html[data-brand="aktiv-2026"] .a26h-mask:has(> .a26h-h3) {
  --a26-mask-rung: var(--a26-t-h3);
}
@supports (clip-path: inset(0px)) {
  html[data-brand="aktiv-2026"] .a26h-mask {
    --a26-mask-head: calc(var(--a26-mask-rung) * 0.12);
    --a26-mask-foot: calc(var(--a26-mask-rung) * 0.16);
    /* The cut, moved outward on both ends. `overflow` above still clips the
       sides; this is the only thing that decides the top and the bottom. */
    clip-path: inset(
      calc(-1 * var(--a26-mask-head)) 0 calc(-1 * var(--a26-mask-foot)) 0
    );
    overflow: visible;
  }
}
html[data-brand="aktiv-2026"] [data-a26-reveal="title"] {
  --a26-rise: var(--dur-reveal);
}
html[data-brand="aktiv-2026"] [data-a26-reveal="title-hero"] {
  --a26-rise: var(--dur-hero);
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="title"] {
  opacity: 1;
  transform: none;
  transition: none;
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="title"] > * {
  /* 110 % of its own box, PLUS whatever the mask's cut moved down (round 9) —
     so the line starts the same distance out of sight as it always did. The
     token is rung-derived, never `em`: see the mask's note. */
  transform: translateY(calc(110% + var(--a26-mask-foot, 0px)));
  transition: transform var(--a26-rise) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal^="title"].bp-revealed > * {
  transform: translateY(0);
}

/* ---- photo --------------------------------------------------------------
   The hero photo's slow settle: the photo inside scales 1.05 -> 1 over 900ms.
   The frame never fades: the hero photo is this page's Largest Contentful
   Paint and an opacity ramp on it is measured as render delay. */
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="photo"] {
  opacity: 1;
  transform: none;
  transition: none;
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="photo"] .a26h-hero-photo {
  transform: scale(1.05);
  transition: transform var(--dur-a26-settle) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="photo"].bp-revealed .a26h-hero-photo {
  transform: scale(1);
}

/* ---- chip ---------------------------------------------------------------
   A video preview's play disc arrives after its frame. */
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="chip"] {
  transform: none;
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="chip"] .a26h-playchip {
  opacity: 0;
  transition:
    opacity var(--dur-reveal) var(--ease-a26),
    transform var(--dur-micro) var(--ease-a26-micro);
  transition-delay: calc(calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1)) + var(--delay-a26-playchip)), 0s;
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="chip"].bp-revealed .a26h-playchip {
  opacity: 1;
}

/* ---- zip ----------------------------------------------------------------
   The page's last word: the bulk-download block rises, and its orange control
   pops scale 0.94 -> 1 at the end. That pop is THE ONE allowed pop on this
   page (design ruling 2026-09-04). The pop lives on a wrapper span so the
   button keeps its own `:active` transform. */
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="zip"] .a26h-bulk-cta {
  transform: scale(0.94);
  transition: transform var(--dur-a26-pop) var(--ease-a26);
  transition-delay: calc(calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1)) + var(--delay-a26-zip-pop));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="zip"].bp-revealed .a26h-bulk-cta {
  transform: scale(1);
}

/* ---- Collapsed accordion rows never reveal ------------------------------
   A `.bp-fade-up` inside a shut <details> is display:none, so the
   IntersectionObserver never reports it intersecting and never adds
   `.bp-revealed` — open the row later and its content sits at opacity 0
   forever. Both boards draw only the FIRST row open, so every reveal below it
   is made inert here rather than left to fail silently. */
html[data-brand="aktiv-2026"].js-reveal .a26h-step:not(:first-of-type) .bp-fade-up,
html[data-brand="aktiv-2026"].js-reveal .a26h-step:not(:first-of-type) [data-a26-reveal],
html[data-brand="aktiv-2026"].js-reveal .a26h-step:not(:first-of-type) [data-a26-reveal] > * {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---- device -------------------------------------------------------------
   The graphics device enters with the base reveal (opacity + the 16px rise
   on the wrapper, above); inside it the stage graphic gets the media reveal —
   a 1.04 -> 1 settle inside the stage's clipped box. The frame itself does
   not scale (spec §2.8). The settle sits on the graphic's button and the
   hover scale on its image, so the two transforms never share an element. */
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="device"] .a26h-stage-graphic {
  transform: scale(1.04);
  transition: transform var(--dur-reveal) var(--ease-a26);
  transition-delay: calc(var(--a26-delay, 0ms) * var(--a26-load-scale, 1));
}
html[data-brand="aktiv-2026"].js-reveal [data-a26-reveal="device"].bp-revealed .a26h-stage-graphic {
  transform: scale(1);
}

/* ============================================================================
   MOBILE LOAD CLOCK.

   On phones the page-load sequence WAS the Largest Contentful Paint (measured
   gate-on, Lighthouse mobile preset, 2026-09-04). Below 1024px the hero runs a
   compressed version of the same sequence — same moves, same order, same
   easing, a fraction of the clock — so every hero element reaches its final
   opacity inside ~400ms. NOTHING outside the hero is touched.
   ============================================================================ */
@media (max-width: 1023px) {
  html[data-brand="aktiv-2026"] .a26h-hero {
    --a26-load-scale: 0.15;
    --a26-fade: var(--dur-micro);
    --dur-a26-draw-load: 200ms;
    --dur-a26-settle: var(--dur-micro);
    --delay-a26-eyebrow-load: 40ms;
  }
  /* The RISE keeps the full signature duration: a transform on text that has
     already painted is not render delay, and the LCP element is the photo. */
  html[data-brand="aktiv-2026"] .a26h-hero [data-a26-reveal="title-hero"] {
    --a26-load-scale: 1;
    --a26-rise: var(--dur-hero);
  }
  /* The kicker and locality fade without travelling. */
  html[data-brand="aktiv-2026"].js-reveal .a26h-hero .a26h-hero-kicker.bp-fade-up,
  html[data-brand="aktiv-2026"].js-reveal .a26h-hero .a26h-hero-locality.bp-fade-up {
    transform: none;
  }
}

/* ============================================================================
   REDUCED MOTION — the accessibility kill switch.

   Every reveal becomes a 200ms opacity fade with zero delay, the signature
   move and the whole page-load sequence land instantly, every keyframe
   animation is off — and every transition list on the page becomes
   OPACITY-ONLY, so nothing under this query can move even in principle
   (a `transform` left in a transition list is a move waiting for a state
   change; the 2026-09-05 perf review counted 97 of them here).

   `!important` is deliberate. The variant rules above run as deep as (0,5,1)
   and grow whenever a variant gains a descendant; a kill switch that has to be
   re-specificity-matched every time someone adds a rule is one that will
   silently stop working.
   ============================================================================ */
@media (prefers-reduced-motion: reduce) {
  html[data-brand="aktiv-2026"] {
    scroll-behavior: auto;
  }
  /* `.a26h-lbdel` is named SEPARATELY because it is not inside `.a26h`: the
     graphic's lightbox is portaled to document.body, so the corner «Del» this
     round puts in it sits outside the hub root and escaped this clamp — it
     computed `background-color, border-color, color, transform` at 0.2s under
     reduced motion until it was named here. Any future a26 surface that
     portals out of the root has to be added on the same line. */
  html[data-brand="aktiv-2026"] .a26h,
  html[data-brand="aktiv-2026"] .a26h *,
  html[data-brand="aktiv-2026"] .a26h *::before,
  html[data-brand="aktiv-2026"] .a26h *::after,
  html[data-brand="aktiv-2026"] .a26h-lbdel,
  html[data-brand="aktiv-2026"] .a26h-lbdel *,
  html[data-brand="aktiv-2026"] .a26h-lbdel *::before,
  html[data-brand="aktiv-2026"] .a26h-lbdel *::after {
    transition-property: opacity !important;
  }
  html[data-brand="aktiv-2026"] .bp-fade-up,
  html[data-brand="aktiv-2026"] .bp-line-trim,
  html[data-brand="aktiv-2026"] [data-a26-reveal],
  html[data-brand="aktiv-2026"] [data-a26-reveal] *,
  html[data-brand="aktiv-2026"] [data-a26-reveal]::before,
  html[data-brand="aktiv-2026"] .a26h-step-chev {
    opacity: 1 !important;
    transform: none !important;
    transition: opacity var(--dur-a26-reduced) linear !important;
    transition-delay: 0s !important;
  }
  /* The chevron still has to point the other way when its row is open — that
     is state, not decoration. */
  html[data-brand="aktiv-2026"] .a26h-step[open] .a26h-step-chev {
    transform: rotate(180deg) !important;
  }
  html[data-brand="aktiv-2026"] [data-a26-reveal]::after,
  html[data-brand="aktiv-2026"] .a26h-pill[data-a26-state="ticked"] svg,
  html[data-brand="aktiv-2026"] .a26h-statusdot,
  html[data-brand="aktiv-2026"] .bp-dot-pulse {
    animation: none !important;
  }
  /* The thumbnail pre-roll is STATE, not decoration: the overlay still has to
     go when the film starts, or it sits on top of a playing video. The blanket
     rules above pin every `[data-a26-reveal]` descendant to opacity 1 and the
     overlay is one, so the live state is restated here at the same strength —
     and its travel collapses to 0s, which is what reduced motion asks for.
     Instant, not absent. */
  html[data-brand="aktiv-2026"] .a26h-thumb {
    transition-duration: 0s !important;
  }
  html[data-brand="aktiv-2026"] [data-a26-live="on"] .a26h-thumb {
    opacity: 0 !important;
  }
}

/* ============================================================================
   ACTION GROUPS — share-first on phones, download-first on desktop.

   This mirrors how the aktiv-2019 hub decides: at the LAYOUT breakpoint, not
   at runtime. Both groups are in the DOM, exactly one is displayed. The
   phone group's share verb is orange (every Del is, rev 1.1 §6.2); the
   desktop group is a download and stays outline.
   ============================================================================ */
html[data-brand="aktiv-2026"] .a26h-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--a26-s-3);
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-actions {
    gap: var(--a26-s-4);
  }
  html[data-brand="aktiv-2026"] .a26h-actions--mobile {
    display: none;
  }
}
html[data-brand="aktiv-2026"] .a26h-actions--desktop {
  display: none;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-actions--desktop {
    display: flex;
  }
}
/* THE SAME SWITCH, APPLIED TO WORDS. On a phone the accordion's verb hands
   the file to the native share sheet; on desktop it is a download. Both
   copies are in the markup and exactly one is shown, at the breakpoint the
   controls already switch on. */
html[data-brand="aktiv-2026"] .a26h-stepcopy--desk {
  display: none;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-stepcopy--phone {
    display: none;
  }
  html[data-brand="aktiv-2026"] .a26h-stepcopy--desk {
    display: block;
  }
}

/* The two-phase save's progress bar and helper lines are siblings of the
   control, not children — they need the row to break rather than sit beside
   the buttons. */
html[data-brand="aktiv-2026"] .a26h-actions .a26h-progress,
html[data-brand="aktiv-2026"] .a26h-actions .a26h-hint,
html[data-brand="aktiv-2026"] .a26h-actions .a26h-postsave,
html[data-brand="aktiv-2026"] .a26h-actions .a26h-notice-inline {
  flex-basis: 100%;
}

/* ============================================================================
   WHAT THE PAGE SAYS WHEN SOMETHING GOES WRONG.

   The hub's safety UI — the in-app-browser and Edge advisories, the
   share-did-not-land offer, the desktop share dialog — keeps its live
   DECISION LOGIC (lib/notice-precedence, lib/save-asset, unforked) and loses
   the aktiv-2019 chrome it used to wear in the middle of this page: a satin
   card, a 12px radius, an info roundel and a dark-red button, which is what an
   agent met under an orange «Del» (Henrik, 2026-09-08).

   All of it is now the page's ONE panel device — white, one 1px chrome-ink
   hairline, square, a mono label, body copy — and its controls are the quiet
   outline pill. No orange in here: rev 1.1 §6.2 spends orange on the verb
   «Del», and a notice's control is always a remedy, never a share.
   ============================================================================ */
/* The outer gutter for a page-width notice. */
html[data-brand="aktiv-2026"] .a26h-notice {
  padding-inline: var(--a26-gutter);
  padding-block-start: var(--a26-s-3);
  width: 100%;
}
@media (min-width: 1024px) {
  html[data-brand="aktiv-2026"] .a26h-notice {
    padding-inline: var(--a26-gutter);
  }
}
/* A notice that belongs to one control sits directly under it, full width. */
html[data-brand="aktiv-2026"] .a26h-notice-inline {
  padding-block-start: var(--a26-s-2);
  width: 100%;
}

html[data-brand="aktiv-2026"] .a26h-notecard {
  gap: var(--a26-s-3);
  max-width: var(--a26-measure);
}
/* Label left, the 44px dismiss target right. */
html[data-brand="aktiv-2026"] .a26h-notecard-head {
  align-items: flex-start;
  display: flex;
  gap: var(--a26-s-4);
  justify-content: space-between;
}
/* A real target: this sits next to a share button on a phone, and a 24px
   close box is the one that gets mis-tapped. The glyph is the page's ink; it
   is chrome, so it never spends the orange. */
html[data-brand="aktiv-2026"] .a26h-notecard-close {
  align-items: center;
  background: transparent;
  border: none;
  color: var(--a26-ink-chrome);
  cursor: pointer;
  display: flex;
  flex-shrink: 0;
  font-size: var(--a26-t-ui);
  height: 44px;
  justify-content: center;
  line-height: 1;
  margin-block-start: -12px;
  margin-inline-end: -12px;
  padding: 0;
  width: 44px;
}
html[data-brand="aktiv-2026"] .a26h-notecard-body {
  color: var(--a26-body);
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-body);
  font-weight: 400 !important;
  line-height: var(--a26-lh-body);
  margin: 0;
}
html[data-brand="aktiv-2026"] .a26h-notecard-action {
  display: flex;
}

/* The post-save line: what happened, and the way back to the app. Conditional
   copy («hvis du valgte …») — a share resolving proves the sheet closed and
   nothing more. The link is a way OUT of this page, not a verb it owns, so it
   is the quiet ink and not the orange. */
html[data-brand="aktiv-2026"] .a26h-postsave {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--a26-s-2);
  padding-block-start: var(--a26-s-2);
}
html[data-brand="aktiv-2026"] .a26h-postsave-link {
  align-items: center;
  color: var(--a26-ink-chrome);
  display: inline-flex;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-mono);
  font-weight: 400 !important;
  line-height: var(--a26-lh-mono-text);
  min-height: 44px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- The share dialog (desktop, or a sheet that refused the file). --------
   The page dimmed behind a single panel. It is the ONE modal this hub opens
   for a share; the lightbox is the other and belongs to the preview, not to a
   verb. */
html[data-brand="aktiv-2026"] .a26h-modal-scrim {
  align-items: center;
  /* NEUTRAL BLACK, alpha held. Wider than the letter of B&Y #2/#7 (which names
     photo washes and the paused-video state) and said out loud for that
     reason: this veil covers the WHOLE page, hero photograph and video posters
     included, so it was the most literally «brunt filter» left on the surface.
     The 0.72 is a dialog backdrop's job — separating a modal from the page —
     not a filter over a picture, so the 20 % cap does not apply to it and the
     alpha is unchanged. */
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  inset: 0;
  justify-content: center;
  padding: var(--a26-s-5);
  position: fixed;
  z-index: 120;
}
html[data-brand="aktiv-2026"] .a26h-modal {
  max-height: 88vh;
  max-width: 420px;
  overflow-y: auto;
  width: 100%;
}
/* Four ways out, two per row on a phone, all of them the quiet control. */
html[data-brand="aktiv-2026"] .a26h-modal-actions {
  display: grid;
  gap: var(--a26-s-2);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* The shared toast bus stays mounted (any shared handler may still publish to
   it), so it gets the page's corner treatment rather than the 2019 radius.
   Its own colour is already this page's deep ink. `!important` because the
   component carries inline styles. */
html[data-brand="aktiv-2026"] [role="status"][aria-live="polite"] {
  border-radius: var(--a26-radius-card) !important;
  font-family: var(--font-a26-body) !important;
  font-weight: 400 !important;
}

/* ---- The route error boundary. -------------------------------------------
   Rarely seen and, until now, system-ui on a white page with a browser-default
   button — the one surface that gave up the design language entirely. The
   markup keeps its inline styles so the aktiv-2019 render is untouched; these
   rules only apply where this stylesheet is loaded, and they are `!important`
   for that reason. */
html[data-brand="aktiv-2026"] .bp-route-error {
  background-color: var(--a26-canvas) !important;
  color: var(--a26-body) !important;
  display: flex;
  flex-direction: column;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-body) !important;
  gap: var(--a26-s-4);
  line-height: var(--a26-lh-body) !important;
  min-height: 60vh;
  padding: var(--a26-s-7) var(--a26-gutter) !important;
}
html[data-brand="aktiv-2026"] .bp-route-error p {
  margin: 0;
  max-width: var(--a26-measure);
}
html[data-brand="aktiv-2026"] .bp-route-error button {
  align-items: center;
  align-self: flex-start;
  background: transparent;
  border: var(--a26-hairline-w) solid var(--a26-ink-chrome);
  border-radius: var(--a26-radius-control);
  color: var(--a26-ink-chrome);
  cursor: pointer;
  display: inline-flex;
  font-family: var(--font-a26-body) !important;
  font-size: var(--a26-t-ui);
  justify-content: center;
  min-height: var(--a26-control-h);
  padding-inline: var(--a26-control-pad);
}
