/* ===== tokens.css ===== */
/* ==========================================================================
   AVELaunch Books — design tokens
   Source of truth: WEBSITE_DESIGN (Figma), page "Dekstop"
   Handoff document v1.0, 7 September 2026, sections 6 and 7
   No colour value may be written anywhere outside this file.
   ========================================================================== */

:root {
  /* --- 6.2 Primitive palette ------------------------------------------- */
  --rich-black-1:      #0B1424;  /* body text, inverse surfaces, 3px strokes */
  --rich-black-2:      #E8EDF5;
  --rich-black-3:      #C7D2E3;  /* 1px hairline, vertical grid lines       */
  --rich-black-4:      #93A3BD;
  --rich-black-5:      #5D6C86;  /* secondary text                          */
  --rich-black-6:      #08101D;
  --rich-black-7:      #050A14;

  --space-cadet-1:     #1B2A57;
  --space-cadet-2:     #EEF2FA;
  --space-cadet-3:     #CBD6EC;
  --space-cadet-4:     #9BAED3;
  --space-cadet-5:     #657BA8;
  --space-cadet-6:     #142042;
  --space-cadet-7:     #0D162D;

  --vista-blue-1:      #7C9EC7;  /* brand surface                           */
  --vista-blue-2:      #F3F7FC;  /* spelled "Vista Vlue 2" in the file      */
  --vista-blue-3:      #DCE8F5;
  --vista-blue-4:      #B7CBE3;
  --vista-blue-5:      #93B1D3;

  --columbia-blue-1:   #C2E6F9;
  --columbia-blue-2:   #FCFEFF;
  --columbia-blue-3:   #EEF8FD;
  --columbia-blue-4:   #D9EEF9;
  --columbia-blue-5:   #CBE8FA;

  --amber-1:           #F2BB16;
  --amber-2:           #F9E08A;
  --amber-3:           #F7CD52;
  --amber-4:           #E0A800;  /* accent: buttons, underlines, active     */

  --editorial-white-1: #F8F7F4;
  --editorial-white-2: #FFFFFF;
  --editorial-white-3: #FDFBF8;
  --editorial-white-4: #EEEAE3;  /* page background                         */

  /* --- 6.3 Semantic layer ----------------------------------------------
     Reference map from the file. The layout binds to primitives, exactly
     as the Figma layers do, so this layer stays a dictionary of roles.     */
  --surface-page:       var(--editorial-white-4);
  --surface-brand:      var(--vista-blue-1);
  --surface-accent:     var(--amber-4);
  --surface-inverse:    var(--rich-black-1);
  --content-primary:    var(--rich-black-1);
  --content-secondary:  var(--rich-black-5);
  --content-on-inverse: var(--editorial-white-4);
  --content-accent:     var(--amber-4);
  --content-on-accent:  var(--rich-black-1);
  --content-on-brand:   var(--rich-black-1);
  --border-strong:      var(--rich-black-1);   /* 3px */
  --border-hairline:    var(--rich-black-3);   /* 1px */
  --border-accent:      var(--amber-4);        /* 3px */
  --action-fill:        var(--amber-4);
  --action-fill-hover:  rgba(255, 255, 255, 0); /* no fill on hover        */
  --action-border-hover: var(--amber-4);

  /* --- 4.1 Grid ---------------------------------------------------------
     1440 reference · 12 columns · Stretch · margin 50 · gutter 25
     Working area 1340. Column width is derived, never written down.       */
  --layout-reference: 1440px;
  --layout-margin:    50px;
  --layout-gutter:    25px;
  --layout-content:   1340px;
  --layout-floor:     1200px;   /* lower bound of the desktop layout       */

  /* --- 4.1 Vertical lines ----------------------------------------------
     Seven lines, step 180 of 1440 = 12.5 % of the window.
     THIS IS THE ONLY PLACE THE POSITIONS EXIST. Both layers — the page
     layer under the content and the header layer over its blurred
     background — read them from here. Writing them twice is what makes
     the two layers drift apart at the header edge.                        */
  --line-step:  12.5%;
  --line-width: 1px;
  --line-color: var(--rich-black-3);

  /* --- 8 Effects --------------------------------------------------------
     One effect on the whole site: BACKGROUND_BLUR 50 on the header plate. */
  --header-blur: 25px;
  --header-plate: rgb(238 234 227 / 0.75);
  --header-height: 61px;

  /* --- Motion ----------------------------------------------------------- */
  --t-fast: 150ms;
  --t-base: 300ms;
}

/* ===== base.css ===== */
/* ==========================================================================
   AVELaunch Books — fonts, typography scale, grid, vertical lines, layout
   intent tags. Handoff sections 4, 5, 7, 15.
   ========================================================================== */

/* --- 15.1 Fonts. Served from our own domain, never a third party. -------- */
@font-face {
  font-family: "Mulish";
  font-style: normal;
  font-weight: 200 1000;
  font-display: swap;
  src: url("../fonts/mulish-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Mulish";
  font-style: normal;
  font-weight: 200 1000;
  font-display: swap;
  src: url("../fonts/mulish-latin-ext-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Mulish";
  font-style: italic;
  font-weight: 200 1000;
  font-display: swap;
  src: url("../fonts/mulish-latin-wght-italic.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Comforter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/comforter-latin-400-normal.woff2") format("woff2");
}

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

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

body {
  margin: 0;
  min-width: var(--layout-floor);
  background: var(--surface-page);
  color: var(--content-primary);
  font-family: "Mulish", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  font-size: 15px;
  line-height: normal;
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; text-decoration: none; }

button, input, textarea, select {
  font: inherit;
  color: inherit;
  margin: 0;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* 9. Keyboard focus is visible on every interactive element: white plate,
   3px accent stroke — the decision taken for the form fields, applied site
   wide because the component sets carry no separate focus variant.        */
:focus-visible {
  outline: 3px solid var(--border-accent);
  outline-offset: 2px;
  background-color: var(--editorial-white-2);
}

/* --- 7.3 Heading trim ---------------------------------------------------
   Headings in the file sit on the cap height, not on the line box. Without
   the trim every heading drops a few pixels and the spacing above it reads
   larger than the macket.                                                  */
.u-trim {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

/* --- 7.2 Type styles ----------------------------------------------------
   Letter spacing comes from Figma as a percentage of the type size, so it
   is written in em and never converted to pixels. Line height is Auto in
   every style, which is line-height: normal, not 100 %.                    */
.t-heading-accent       { font-family: "Comforter", cursive; font-weight: 400; font-size: 100px; letter-spacing: 0; text-transform: uppercase; }
.t-heading-accent-small { font-family: "Comforter", cursive; font-weight: 400; font-size: 100px; letter-spacing: 0; }
.t-heading              { font-weight: 1000; font-size: 50px; letter-spacing: 0.1em;  text-transform: uppercase; }
.t-heading-wide         { font-weight: 1000; font-size: 50px; letter-spacing: 0.06em; text-transform: uppercase; }
.t-heading-wide-light   { font-weight: 200;  font-size: 50px; letter-spacing: 0.06em; text-transform: uppercase; }
.t-subheading           { font-weight: 400;  font-size: 25px; letter-spacing: 0;      text-transform: uppercase; }
.t-intro                { font-weight: 400;  font-size: 25px; letter-spacing: 0; }
.t-intro-black          { font-weight: 1000; font-size: 25px; letter-spacing: 0;      text-transform: uppercase; }
.t-intro-black-wide     { font-weight: 1000; font-size: 25px; letter-spacing: 0.1em;  text-transform: uppercase; }
.t-base                 { font-weight: 400;  font-size: 15px; letter-spacing: 0; }
.t-base-black           { font-weight: 1000; font-size: 15px; letter-spacing: 0; }
.t-base-italic          { font-weight: 400;  font-size: 15px; font-style: italic; }
.t-base-down-black      { font-weight: 1000; font-size: 15px; text-transform: lowercase; }
.t-base-up              { font-weight: 400;  font-size: 15px; text-transform: uppercase; }
.t-base-up-black        { font-weight: 1000; font-size: 15px; text-transform: uppercase; }
.t-base-up-black-wide   { font-weight: 1000; font-size: 15px; letter-spacing: 0.1em;  text-transform: uppercase; }
.t-label                { font-weight: 400;  font-size: 25px; letter-spacing: 0.1em;  text-transform: uppercase; }
.t-label-wide           { font-weight: 400;  font-size: 25px; letter-spacing: 0.6em;  text-transform: uppercase; }
.t-label-big            { font-weight: 200;  font-size: 100px; text-transform: uppercase; }
.t-label-big-black      { font-weight: 1000; font-size: 100px; text-transform: uppercase; }

.u-secondary { color: var(--content-secondary); }
.u-accent    { color: var(--content-accent); }

/* --- 4.1 / 4.2 Working area ---------------------------------------------
   Above 1440 the working area holds at 1340 and centres; the margins grow.
   Between 1200 and 1440 the margin stays 50, the gutter stays 25, the
   columns narrow. Type sizes do not change.                               */
.container {
  width: min(var(--layout-content), 100% - var(--layout-margin) * 2);
  margin-inline: auto;
}

/* 12-column helper. The column width is derived from the grid, never set. */
.grid12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--layout-gutter);
}

/* --- 5.1 Intent tags ----------------------------------------------------
   Five values cover all thirty-nine hand-composed blocks. Where Auto Layout
   in the file disagrees with the tag, the tag wins.                        */

/* fluid — lives inside the working area and narrows with it. Default. */
.is-fluid { width: 100%; }

/* flow — a row of equal elements that wraps when it stops fitting.
   The gap equals the gutter. The count per row is not fixed.              */
.is-flow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--layout-gutter);
}
.is-flow > * { flex: 1 1 var(--flow-basis, 430px); min-width: 0; }

/* bleed:both — runs the full window width both sides. Text and cards
   inside stay in the working area.                                        */
.is-bleed-both {
  width: 100vw;
  margin-left: calc(50% - 50vw);
}

/* bleed:left / bleed:right — out past one margin only, never both.
   --bleed-stop is the macket coordinate of the edge that stays put,
   expressed as a share of the working area.                               */
.is-bleed-left {
  margin-left: calc(50% - 50vw);
  margin-right: var(--bleed-stop, 0%);
}
.is-bleed-right {
  margin-right: calc(50% - 50vw);
  margin-left: var(--bleed-stop, 0%);
}

/* --- 4.1 Vertical lines -------------------------------------------------
   One component, two placements. Positions are read from --line-step in
   tokens.css and exist nowhere else, so the page layer and the header layer
   cannot drift apart.                                                      */
.gridlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.gridlines i {
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--line-width);
  background: var(--line-color);
  left: calc(var(--n) * var(--line-step));
}

/* The page layer sits under every section, the full height of the document.
   The header is the one exception: it keeps its own sticky positioning and
   rides above, because it draws its own copy of the lines over its plate. */
/* Bleeding blocks are drawn past the window edge on purpose — an amber band
   that runs off the left, a roller whose next card is cut by the right. The
   page clips them at the window. `clip` and not `hidden`: hidden would make
   this a scroll container and the pinned header would stop pinning. */
.page {
  position: relative;
  overflow-x: clip;
}
.page > .gridlines { z-index: 0; }
.page > *:not(.gridlines):not(.site-header):not(.site-up) { position: relative; z-index: 1; }
.page > .site-header { z-index: 2; }

/* Skip link — visible only once it takes focus. */
.skip-link {
  position: absolute;
  left: var(--layout-margin);
  top: 0;
  z-index: 10;
  transform: translateY(-200%);
  padding: 12px 25px;
  background: var(--editorial-white-2);
  color: var(--content-primary);
  font-weight: 1000;
  font-size: 15px;
  text-transform: uppercase;
  transition: transform var(--t-fast);
}
.skip-link:focus-visible { transform: translateY(0); }

/* --- Vertical rhythm between the blocks ---------------------------------
   The file stacks the screen's blocks on a fixed rhythm, and it is defined
   here once rather than inside each section: a section owns its own height,
   never the air around it.

   Read off the Main screen (1:3): the header's box ends at 111 and the first
   block starts at 180; every neighbouring pair of blocks sits 150 apart; the
   footer sits 100 below the last one.

   150 is only the Main screen's number. Services runs 150 · 100 · 0, How It
   Works runs 100 below its halfway point, and the gap under the header is a
   different number on every screen. So the default lives here and a block
   that departs from it writes its own value once, in the markup, as
   `style="--gap: 100px"` on the <section> — the measured Figma number, next
   to the block it belongs to, still not a margin the section sets on itself.

   The FAQ on Main carries `--gap: 0`: its full-width blue fill is meant to
   start exactly where the founder block above it ends.                      */
:root {
  --block-gap: 150px;
  --block-gap-first: 69px;   /* header box 111 → first block 180 */
  --block-gap-footer: 100px;
}

main > section + section  { margin-top: var(--gap, var(--block-gap)); }
main > section:first-child { margin-top: var(--gap, var(--block-gap-first)); }
.page > .site-footer { margin-top: var(--gap-footer, var(--block-gap-footer)); }

/* --- 13.3 Anchors -------------------------------------------------------
   Smooth scroll that accounts for the pinned header, so the target block
   does not hide underneath it.                                            */
html { scroll-behavior: smooth; }
[id] { scroll-margin-top: calc(var(--header-height) + 50px); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Below the 1200 floor ------------------------------------------------
   The design stops at 1200: below that there is no narrower composition to
   fall back to, and `min-width` on its own gave a horizontal scrollbar — the
   headline cut off the left edge, half the hero off the right. A window at
   900 is not a phone; it is a laptop or a half-screen window, and a page you
   have to scroll sideways to read is broken in the only sense that matters.

   So the page keeps its 1200 layout and is scaled down to fit the window.
   Everything stays in proportion and simply reads smaller. This is not a
   narrow layout and it is no substitute for one — it is what the site does
   until a narrow composition is drawn.

   The scale itself cannot be written here: `zoom` needs a plain ratio, and
   no CSS expression turns a viewport width into one — dividing 100vw by 1200
   yields a length, which `zoom` rejects. So it is set by the small inline
   script the build puts at the top of every <body>, and `zoom` rather than
   `transform: scale()` because a transform would make the pinned header and
   the scroll-to-top control position against the transformed box instead of
   the window, and both would come unstuck.                                 */

/* An inline link inside body copy. The site has no underlines anywhere, so
   a link in the middle of a sentence has to be told apart some other way:
   it carries the accent colour and a 1px rule that thickens on hover. */
.u-link-inline {
  color: var(--content-accent);
  border-bottom: 1px solid currentColor;
  transition: border-bottom-width var(--t-fast), color var(--t-fast);
}
.u-link-inline:hover,
.u-link-inline:focus-visible {
  border-bottom-width: 3px;
}

/* ===== header.css ===== */
/* ==========================================================================
   Site header — Figma component set 504:2789, instance 20:1973 on Main.
   Load AFTER css/base.css.

   Full window width, 61px tall, pinned to the top of the window. Three
   layers, bottom to top:

     1. the plate  — Editorial White 4 at 75 % over a background blur
                     (Figma "Rectangle 13", 1440 x 61)
     2. the lines  — the page's own .gridlines component, drawn a second
                     time so the seven lines sit OVER the plate
     3. the logo and the menu

   Geometry: the seven lines and the seven menu cells are the same seven
   positions. They are read from --line-step in tokens.css and appear
   nowhere else, so the page's line layer and the header's cannot drift.
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--header-height);
  /* Starts one page margin down; the page's own lines show in that strip. */
  margin-top: var(--layout-margin);
}

/* base.css pins every child of .page with `position: relative` at a higher
   weight than a single class, so the sticky behaviour is restated here at
   matching specificity. Width stays `auto` — the header must measure the
   same box as .page, not 100vw, or the scrollbar would offset its lines by
   a few pixels against the page's. */
.page > .site-header {
  position: sticky;
  z-index: 10;
}

/* --- 1. The plate ------------------------------------------------------- */
.site-header__plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--header-plate);
  -webkit-backdrop-filter: blur(var(--header-blur));
  backdrop-filter: blur(var(--header-blur));
}

/* --- 2. The lines -------------------------------------------------------
   The only modifier the shared component needs: it is lifted above the
   plate. The page layer keeps z-index 0 and stays under the content, so
   what shows inside the header is this crisp set at full strength, never
   the page's set dimmed and blurred through the translucent plate.       */
.site-header__lines {
  z-index: 1;
}

/* --- 3. Logo ------------------------------------------------------------ */
.site-header__logo {
  position: absolute;
  z-index: 2;
  left: var(--layout-margin);
  top: 50%;
  transform: translateY(-50%);
}

/* 15px tall, the wordmark's own ratio gives the width (107.45 in the
   macket). Fixed to the window margin, not to a share of the width. */
.site-header__logo img {
  width: auto;
  height: 15px;
}

/* --- 3. Menu ------------------------------------------------------------
   Each cell's line is at --n * --line-step; the label sits one gutter to
   the right of it. The cell width (150 in the macket) is never needed —
   the next cell is placed from the next line, not from this one's edge.  */
.site-header__nav {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* The nav box covers the whole header, including the logo. It is
     transparent but would still take the clicks, so it is made inert and
     only the menu items themselves are given back to the pointer. */
  pointer-events: none;
}

.site-header__item {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  pointer-events: auto;
  left: calc(var(--n) * var(--line-step) + var(--layout-gutter));
}

.site-header__link {
  white-space: nowrap;
  transition: color var(--t-fast);
}

/* Active page. The five variants in the set carry no other difference at
   this height, so one rule covers Main, Services, Process, Results and
   About. Styled off the attribute so the markup cannot drift from it. */
.site-header__link[aria-current="page"],
.site-header__link:hover,
.site-header__link:focus-visible {
  color: var(--content-accent);
}

/* --- 4. The sub-navigation ----------------------------------------------
   Three of the five header variants in the set are 113 tall instead of 61:
   Services (966:7456), Results (521:2698) and About (521:3038). The extra
   52 is a second row of links that hangs under the item that owns it —
   All services / Discovery Sprint under Services, Author Stories / Free
   Resources under Results, Our Team & Story / FAQ / Contact under About.

   Each sub-item sits on the SAME seven positions as the bar above it, one
   gutter right of its line, and the group's plate covers only its own
   columns. The rest of the row is bare: the page shows through it, with
   the seven lines carried down across the full width (Figma "Group 75").

   The block is a child of the <li> that opens it, so :hover and
   :focus-within on that item are the entire interaction — no script, and
   the pointer can travel down into the row without losing the hover
   because it never leaves the <li>'s subtree.

   It is an OVERLAY, not flow: on Services the hero deliberately starts at
   110 and runs up behind the whole header. A page whose first block is
   meant to start below the open row writes that into its own --gap.     */
.site-header__sub {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 52px;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-fast) ease, visibility var(--t-fast);
  /* The nav box above is inert so it cannot swallow clicks meant for the
     page; this row is its own box and takes its own. */
  pointer-events: auto;
}

/* The block is a sibling of the menu, not a child of the item that opens it:
   the item is itself absolutely positioned, so a descendant would be laid
   out against that one narrow cell instead of across the header. :has()
   carries the relationship instead.

   Three states, in this order, and the order is the whole logic:

     1. a page that belongs to a group holds that group's row open;
     2. the moment the pointer or the caret lands on ANY opening item, every
        row closes — otherwise the page's own row and the hovered one draw
        on top of each other in the same 52px strip, which is what the
        header did on all seven section pages;
     3. the row belonging to what is actually being pointed at opens.

   Step 3 also keeps the row open while the pointer is inside it, so
   travelling down from the label into the links does not close it. */

/* 1 — held open by the page */
.site-header[data-subnav="services"] .site-header__sub[data-group="services"],
.site-header[data-subnav="results"]  .site-header__sub[data-group="results"],
.site-header[data-subnav="about"]    .site-header__sub[data-group="about"] {
  opacity: 1;
  visibility: visible;
}

/* 2 — anything being pointed at or tabbed to closes all of them first */
.site-header:has(.site-header__link[data-opens]:hover) .site-header__sub,
.site-header:has(.site-header__link[data-opens]:focus-visible) .site-header__sub,
.site-header:has(.site-header__sub:hover) .site-header__sub,
.site-header:has(.site-header__sub:focus-within) .site-header__sub {
  opacity: 0;
  visibility: hidden;
}

/* 3 — and only the one being pointed at opens */
.site-header:has(.site-header__link[data-opens="services"]:hover) .site-header__sub[data-group="services"],
.site-header:has(.site-header__link[data-opens="services"]:focus-visible) .site-header__sub[data-group="services"],
.site-header:has(.site-header__sub[data-group="services"]:hover) .site-header__sub[data-group="services"],
.site-header:has(.site-header__sub[data-group="services"]:focus-within) .site-header__sub[data-group="services"],
.site-header:has(.site-header__link[data-opens="results"]:hover) .site-header__sub[data-group="results"],
.site-header:has(.site-header__link[data-opens="results"]:focus-visible) .site-header__sub[data-group="results"],
.site-header:has(.site-header__sub[data-group="results"]:hover) .site-header__sub[data-group="results"],
.site-header:has(.site-header__sub[data-group="results"]:focus-within) .site-header__sub[data-group="results"],
.site-header:has(.site-header__link[data-opens="about"]:hover) .site-header__sub[data-group="about"],
.site-header:has(.site-header__link[data-opens="about"]:focus-visible) .site-header__sub[data-group="about"],
.site-header:has(.site-header__sub[data-group="about"]:hover) .site-header__sub[data-group="about"],
.site-header:has(.site-header__sub[data-group="about"]:focus-within) .site-header__sub[data-group="about"] {
  opacity: 1;
  visibility: visible;
}

/* The group's own piece of the plate: from its first line to one past its
   last, so the blur ends on a line and not in the middle of a cell. */
.site-header__sub-plate {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--from) * var(--line-step));
  width: calc(var(--span) * var(--line-step) + var(--line-width));
  /* The file gives this the same Editorial White 4 at 75 % as the bar above
     it, but it only ever draws the header over the cream hero. On a live
     page the sticky header travels over the blue and amber bands, and there
     a 75 % plate that covers three columns and not the rest reads as a grey
     smear cut through the headline behind it — the bar gets away with it
     because it spans the full width, this row does not. So the row's own
     plate is opaque: the two links stay legible over anything, and the strip
     reads as a panel that belongs to the menu instead of a smudge. */
  background: var(--surface-page);
}

/* Figma "Line 39": 1px at y 62, i.e. the first pixel of this row, spanning
   exactly the group's columns. */
.site-header__sub-rule {
  position: absolute;
  top: 1px;
  height: var(--line-width);
  left: calc(var(--from) * var(--line-step));
  width: calc(var(--span) * var(--line-step) + var(--line-width));
  background: var(--line-color);
  z-index: 2;
}

/* The seven lines continue down through the whole row, group or not. */
.site-header__sub-lines { z-index: 1; }

.site-header__submenu {
  position: absolute;
  inset: 0;
  z-index: 3;
}

/* Macket: label baseline at y 76 within the 113 header, i.e. 15 into this
   row; same one-gutter offset from the line as the bar above. */
.site-header__subitem {
  position: absolute;
  top: 15px;
  left: calc(var(--n) * var(--line-step) + var(--layout-gutter));
  pointer-events: auto;
}

/* Sentence case, Base Regular — the one place on the site where a menu
   label is not set in capitals. */
.site-header__sublink {
  white-space: nowrap;
  transition: color var(--t-fast);
}

.site-header__sublink[aria-current="page"],
.site-header__sublink:hover,
.site-header__sublink:focus-visible {
  color: var(--content-accent);
}

/* ===== footer.css ===== */
/* ==========================================================================
   Site footer — Figma symbol 152:1464, instance 966:8527.
   Load AFTER css/base.css.

   Full window width, 415 tall in the macket, Vista Blue 1. The fill is
   opaque, so it covers the page's vertical line layer — the macket shows
   no lines inside the footer.

   Vertical rhythm, read off the macket (footer top = 0):

        50  logo, 15 tall
        83  hairline, full working area
        98  tagline          |  50   Company / Services / Contact headings
       134  social icons     |  98   first link of each column
       184  Barcelona office | 289   last link of the Services column
       339  hairline
       354  legal links and copyright
       415  foot

   The right-hand link block starts level with the logo, so the first
   hairline crosses it. That is why the two halves are one grid with fixed
   rows rather than two stacked blocks: the rules span both columns while
   the link block spans the rows above and below the first of them.
   ========================================================================== */

.site-footer {
  background: var(--vista-blue-1);
  padding-block: var(--layout-margin);
  min-height: 415px;
}

.site-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  /* logo band · hairline · body · hairline · bottom bar */
  grid-template-rows: 33px var(--line-width) 255px var(--line-width) auto;
}

/* --- Logo --------------------------------------------------------------- */
.site-footer__logo {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
}

.site-footer__logo img {
  width: auto;
  height: 15px;
}

/* --- Hairlines ---------------------------------------------------------- */
.site-footer__rule {
  grid-column: 1 / -1;
  margin: 0;
  border: 0;
  height: var(--line-width);
  background: var(--rich-black-1);
}
.site-footer__rule--top    { grid-row: 2; }
.site-footer__rule--bottom { grid-row: 4; }

/* --- Left half: tagline, socials, office -------------------------------- */
.site-footer__brand {
  grid-column: 1;
  grid-row: 3;
}

.site-footer__tagline { margin-top: 14px; }

.site-footer__social {
  display: flex;
  align-items: center;
  gap: var(--layout-gutter);
  margin-top: var(--layout-gutter);
}

.site-footer__office {
  display: block;
  font-style: normal;
  margin-top: var(--layout-gutter);
}
.site-footer__office span { display: block; }

/* --- Right half: three link columns -------------------------------------
   Spans from the logo band down past the first hairline, exactly as in the
   macket. 169 wide each, 50 apart — two gutters.                          */
.site-footer__nav {
  grid-column: 2;
  grid-row: 1 / 4;
  align-self: start;
  display: flex;
  gap: calc(var(--layout-gutter) * 2);
}

.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: 30px;
  width: 169px;
}

.site-footer__list {
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
  align-items: start;
}

/* --- Bottom bar --------------------------------------------------------- */
.site-footer__bottom {
  grid-column: 1 / -1;
  grid-row: 5;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--layout-gutter);
  margin-top: 14px;
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--layout-gutter);
}

.site-footer__copy {
  text-align: right;
  white-space: nowrap;
}

/* --- Links -------------------------------------------------------------- */
.site-footer a {
  transition: color var(--t-fast);
}
.site-footer a:hover,
.site-footer a:focus-visible {
  color: var(--content-accent);
}

/* --- The reduced footer — Figma `Footer_min` 917:7587, 1440 x 319 --------
   Used by the two paid-traffic landing pages. Same brand block, same legal
   row, same hairline; the three site-map columns are replaced by "Contact"
   and two ways to reach us, and the second hairline is gone.

   Measured from the symbol: logo 50,50 · rule y 83 · tagline y 98 · social
   y 134 · office y 184 · legal row and copyright y 258. With the 50 page
   padding those become a 33 logo band, the rule, a 160 body and the bottom
   bar — 319 in total.                                                     */
.site-footer--min {
  min-height: 319px;
}

.site-footer--min .site-footer__grid {
  /* logo band · hairline · body · bottom bar */
  grid-template-rows: 33px var(--line-width) 160px auto;
}

/* "Contact" sits on the logo's line, hard right. */
.site-footer--min .site-footer__contact {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  align-self: start;
}

/* WhatsApp and the address share the tagline's line, right aligned. */
.site-footer--min .site-footer__reach {
  grid-column: 2;
  grid-row: 3;
  justify-self: end;
  align-self: start;
  display: flex;
  gap: 50px;
  margin-top: 14px;
}

.site-footer--min .site-footer__reach a {
  transition: color var(--t-fast);
}
.site-footer--min .site-footer__reach a:hover,
.site-footer--min .site-footer__reach a:focus-visible {
  color: var(--content-accent);
}

/* The bottom bar moves up one row, since there is no second hairline. */
.site-footer--min .site-footer__bottom {
  grid-row: 4;
}

/* ===== up.css ===== */
/* ==========================================================================
   Scroll-to-top control — `Button_form` 657:4075, macket 50,235 · 61 × 72.
   Load AFTER css/base.css.

   Fixed to the window at the page margin, at the same y the file draws it,
   so it sits in the empty strip left of the first vertical line and clear of
   the header. The label is set on its side reading bottom to top, which is
   what makes the box taller than it is wide.
   ========================================================================== */

.site-up {
  position: fixed;
  left: var(--layout-margin);
  /* The file draws this at y 235 — a static position on a page that does not
     scroll. As a floating control at the same coordinate it sits on top of
     whatever band happens to be passing: the Services list on the homepage
     runs its blue fill from the page margin, and the button covered the first
     row's line. So it keeps the file's x and moves to the foot of the window,
     out of the reading column and where a back-to-top control is looked for. */
  bottom: var(--layout-margin);
  z-index: 11;                      /* over the header's 10 */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 25px;
  border: 0;
  background: var(--action-fill);
  color: var(--content-on-accent);
  box-shadow: inset 0 0 0 3px var(--action-fill);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-base) ease,
              background-color var(--t-fast) ease,
              box-shadow var(--t-fast) ease;
}

/* `hidden` is removed by the script; `data-shown` is what fades it in, so
   the control is never a dead button and never a flash on load. */
.site-up[data-shown] { opacity: 1; }

.site-up__label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);        /* reads bottom to top, as in the file */
  white-space: nowrap;
}

/* pas → hov on Button_form: the fill empties, the amber stroke stays, and
   the box does not change size because the stroke is drawn inside. */
.site-up:hover,
.site-up:focus-visible {
  background: var(--action-fill-hover);
  box-shadow: inset 0 0 0 3px var(--action-border-hover);
}

/* ===== assessments/intro.css ===== */
/* ==========================================================================
   Assessments — landing headline.  Intent tag: fluid.
   Figma: Assessments_1 (649:3672) / Screen 1 (739:4259) / frame 739:4249.
   Macket 164..1276 x 236..482 — ten columns with their gutters, so the block
   is grid-column 2 / span 10 and never needs a pixel width of its own.

     heading group  y 236..321   85   accent at 0, Mulish heading at 50
     gap                         50
     lede           y 371..482  111   657 wide, flush right in the 1112
   ========================================================================== */

.s-intro__block {
  grid-column: 2 / span 10;
  display: flex;
  flex-direction: column;
  gap: 50px;
  align-items: flex-end;
}

/* "Is your" in Comforter lies over the Mulish heading: the script's cap top
   at 236, the heading's at 286. Both are trimmed, so 50 is the exact offset,
   and it is padding rather than a margin — a margin on the Mulish line
   collapses through this box and carries the script word down with it. */
.s-intro__title {
  position: relative;
  align-self: stretch;
  padding-top: 50px;
  font: inherit;
}
.s-intro__script {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
}
.s-intro__head {
  display: block;
}

/* 657 of the 1112 — six columns with their gutters, on the right edge. */
.s-intro__lede {
  width: 59.0827%;
}

/* ===== assessments/about.css ===== */
/* ==========================================================================
   Assessments — "what you'll get" band.  Intent tag: fluid.
   Figma: Assessments_1 (649:3672) / frame 739:4258, macket y 632 -> 973.

   The fill is the working area wide (1340), not the window: it starts at the
   left margin and stops at the right one, so it is an ordinary child of
   .container and carries no bleed helper.

     band      341 = 50 + 241 + 50, padding 114 left and right
     inner    1112 = 1340 - 2 x 114
       pitch   544  kicker 11 + 25 + claim 49 = 85, gap 50, button 61 = 196
       gap     112
       pillars 456  a 3px rule, 26, then a 430 column of three 47-tall items
   ========================================================================== */

.s-about__band {
  background: var(--vista-blue-1);
  padding: 50px 8.5075%;         /* 114 / 1340 */
}
.s-about__inner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

/* --- Left: the promise and the way in ----------------------------------- */
.s-about__pitch {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 50px;
  width: 48.9209%;               /* 544 / 1112 */
}
.s-about__pitch-words {
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
  width: 100%;
}

/* Button_form: Amber 4, 25 all round, the label on its cap height so
   25 + 11 + 25 gives the 61 of the macket. The border matches the fill at
   rest so the box does not change size when hover empties it.              */
.s-about__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  border: 3px solid var(--action-fill);
  background: var(--action-fill);
  color: var(--content-on-accent);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.s-about__cta:hover,
.s-about__cta:focus-visible {
  background: var(--action-fill-hover);
  border-color: var(--action-border-hover);
}

/* --- Right: the three things the questions measure ----------------------- */
.s-about__pillars {
  display: flex;
  width: 41.0072%;               /* 456 / 1112 */
}

/* Line 53 (739:4240): a 3px Editorial White 4 rule the full height of the
   column. It is drawn here rather than exported — it is one stroke in a
   palette colour, and an <img> could not be recoloured from a token.       */
.s-about__rule {
  flex: 0 0 3px;
  align-self: stretch;
  margin-right: 23px;
  background: var(--editorial-white-4);
}

/* 430 of the 456 at the reference width; below it the column narrows with the
   working area rather than pushing the band out of the page.               */
.s-about__list {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 50px;
  min-width: 0;
}
.s-about__item {
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
}

/* ===== assessments/qhead.css ===== */
/* ==========================================================================
   Assessments — question screen header.  Intent tag: fluid.
   Figma: Assessments_2 (739:4260) and its two siblings.

     up tab      macket  50..111 x 163..235   61 x 72, rotated a quarter turn
     title       macket 164..1276 x 236..321  script at 236, Mulish at 286
     counter     macket 732..1276 x 303..321  right aligned on the title

   The block box is 163..321, which is 158 tall: 73 of padding for the tab,
   then the 85-tall title group. The tab is taken out of flow so the title
   keeps the block's height honest.
   ========================================================================== */

.s-qhead[hidden] { display: none; }

.s-qhead__inner {
  position: relative;
  padding-top: 73px;
  padding-left: 8.5075%;         /* 114 / 1340 */
  padding-right: 4.7761%;        /*  64 / 1340 — the title column stops at
                                    macket 1276, not at the right margin  */
}/* --- Title --------------------------------------------------------------
   The Comforter word lies over the Mulish heading in one box: script cap top
   at 236, heading cap top at 286. Both are trimmed, so the offset is 50, and
   it is padding rather than a margin — a margin on the Mulish line collapses
   through this box and carries the script word down with it.               */
.s-qhead__title {
  position: relative;
  padding-top: 50px;
  font: inherit;
}
.s-qhead__title[hidden] { display: none; }
.s-qhead__script {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
}
.s-qhead__head {
  display: block;
}

/* Flush with the right edge of the title column and sitting on the same
   baseline as the heading: 18 of cap height ending on 321.                 */
.s-qhead__count {
  position: absolute;
  right: 0;
  bottom: 0;
  text-align: right;
}

/* ===== assessments/quiz.css ===== */
/* ==========================================================================
   Assessments — the question panel.  Intent tag: fluid.
   Figma: Assessments_2 (739:4260) / Section 1 (1154:8768), and the two
   sibling screens 741:4763 and 741:4965.

     panel     macket   50..1390 x 371..1939   Vista Blue 1, 1568 tall
       back    macket  110..182  x 421..442
       body    macket  164..1276 x 521..1789   1112 wide, 150 in from the top
         q     455 legend, 89, 568 options; 100 between questions
         acts  50 under the last question: 61-tall button, 25, the hint

   The plate is the working area wide, not the window: no bleed helper.
   ========================================================================== */

.s-quiz[hidden] { display: none; }

.s-quiz__panel {
  position: relative;
  background: var(--vista-blue-1);
  padding: 150px 8.5075%;        /* 114 / 1340 */
}

/* --- Back ---------------------------------------------------------------
   Main_S11_Arrows turned to point left, then the label. Taken out of flow so
   the 150 of padding above the questions stays the macket's number.        */
.s-quiz__back {
  position: absolute;
  left: 4.5224%;                 /* 60.6 / 1340 — macket x 110.6 */
  top: 50px;
  display: inline-flex;
  align-items: center;
  gap: 20px;
  color: var(--content-on-brand);
}
.s-quiz__back-arrow {
  flex: 0 0 auto;
  width: 10.607px;
  height: 21.213px;
}
.s-quiz__back:hover,
.s-quiz__back:focus-visible {
  color: var(--content-accent);
}

/* --- Groups -------------------------------------------------------------
   Three groups of three questions. One is shown at a time; the other two
   stay in the markup so nothing has to be fetched or rebuilt to go back.  */
.s-quiz__group[hidden] { display: none; }

.s-quiz__questions {
  display: flex;
  flex-direction: column;
  gap: 100px;
}

/* --- One question -------------------------------------------------------
   A real fieldset. The legend is taken out of flow into the left column:
   in every one of the nine questions the answer stack is the taller of the
   two, so the fieldset keeps the macket's height from the options alone.  */
.s-quiz__q {
  position: relative;
  margin: 0;
  padding: 0;
  border: 0;
  min-inline-size: 0;
}
.s-quiz__legend {
  position: absolute;
  left: 0;
  top: 0;
  width: 40.9173%;               /* 455 / 1112 */
  padding: 0;
  color: var(--content-on-brand);
}
.s-quiz__options {
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
  width: 51.0791%;               /* 568 / 1112 */
  margin-left: 48.9209%;         /* 544 / 1112 */
}

/* --- Assessment_answer, component set 741:4414 --------------------------
   Pas  Editorial White 4 plate, the label Mulish Regular 15 uppercase.
   Act  Amber 4 plate, the label Mulish ExtraBlack 15 uppercase.
   25 all round, so a one-line answer is 25 + 11 + 25 = 61 and a two-line
   one is 80, exactly as the macket draws them.

   The set carries no Hov variant. Hover and keyboard focus therefore borrow
   the Button_form idea instead — a 3px Amber 4 ring — so a pointer and a
   caret get the same feedback and nothing moves when they do.             */
.s-quiz__opt {
  position: relative;
  display: flex;
  align-items: center;
  padding: 25px;
  background: var(--editorial-white-4);
  color: var(--content-primary);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, box-shadow var(--t-fast) ease;
}
.s-quiz__opt:hover {
  box-shadow: inset 0 0 0 3px var(--action-border-hover);
}
.s-quiz__opt:has(.s-quiz__radio:checked) {
  background: var(--action-fill);
}

/* The control itself covers the plate so the whole row is the hit area; it
   is transparent, and the ring below is what a focused answer looks like. */
.s-quiz__radio {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  appearance: none;
  opacity: 0;
  cursor: pointer;
}
.s-quiz__opt:has(.s-quiz__radio:focus-visible) {
  outline: 3px solid var(--border-accent);
  outline-offset: 2px;
}

.s-quiz__opt-label {
  flex: 1 0 0;
  min-width: 0;
}

/* --- Actions ------------------------------------------------------------ */
.s-quiz__actions {
  display: flex;
  align-items: center;
  gap: var(--layout-gutter);
  margin-top: 50px;
}

/* Button_form: 22 of padding inside a 3px border is the macket's 25, and the
   border matching the fill keeps the box the same size when hover empties
   it. 25 + the label's 11 cap height + 25 = 61.                           */
.s-quiz__next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  border: 3px solid var(--action-fill);
  background: var(--action-fill);
  color: var(--content-on-accent);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.s-quiz__next:hover,
.s-quiz__next:focus-visible {
  background: var(--action-fill-hover);
  border-color: var(--action-border-hover);
}
.s-quiz__hint {
  color: var(--content-on-brand);
}

/* ===== assessments/ghead.css ===== */
/* ==========================================================================
   Assessments — gate headline.  Intent tag: fluid.
   Figma: Assessments_5 (741:5153) / Title 741:5172, macket 164..1276 x
   236..384. The script word sits on 236 and the Mulish heading on 286; the
   heading runs to two lines, which is what makes the group 148 rather than
   the 85 the question screens carry.
   ========================================================================== */

.s-ghead[hidden] { display: none; }

.s-ghead__inner {
  padding-left: 8.5075%;         /* 114 / 1340 */
  padding-right: 4.7761%;        /*  64 / 1340 */
}

/* Padding and not a margin: a margin on the Mulish line collapses through
   this box and carries the script word down with it.                      */
.s-ghead__title {
  position: relative;
  padding-top: 50px;
  font: inherit;
}
.s-ghead__script {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
}
.s-ghead__head {
  display: block;
}

/* ===== assessments/gate.css ===== */
/* ==========================================================================
   Assessments — the gate.  Intent tag: fluid.
   Figma: Assessments_5 (741:5153) / Section 1 (741:5573), macket
   164..1390 x 529..1001.

     inner   1226 = 544 words + 25 + 657 form, flush with the right margin
     form     657 x 472   Vista Blue 1, 25 top, 25 sides, 50 bottom
       fields 607  email 62, 50, segment 174  = 286
       gap     50
       button  61
   ========================================================================== */

.s-gate[hidden] { display: none; }

.s-gate__inner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 91.4925%;               /* 1226 / 1340 */
  margin-left: 8.5075%;          /*  114 / 1340 */
}

/* --- Words -------------------------------------------------------------- */
.s-gate__words {
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
  width: 44.3719%;               /* 544 / 1226 */
}

/* --- The form plate ----------------------------------------------------- */
.s-gate__form {
  display: flex;
  flex-direction: column;
  gap: 50px;
  width: 53.5889%;               /* 657 / 1226 */
  padding: 25px 25px 50px;
  background: var(--vista-blue-1);
}
.s-gate__fields {
  display: flex;
  flex-direction: column;
  gap: 50px;
}

/* --- Email, Main_S14_Form_text_card (set 144:914) ------------------------
   Editorial White 4 plate, no border at rest, 15 of padding: 15 + the 11 cap
   height + 15 is the 41 of the macket. The Act variants draw the focus
   stroke on the plate edge rather than 2 outside it.                       */
.s-gate__field {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.s-gate__label {
  color: var(--content-on-brand);
}
.s-gate__plate {
  width: 100%;
  height: 41px;
  padding: 0 15px;
  border: 0;
  background: var(--editorial-white-4);
  color: var(--content-primary);
}
.s-gate__plate::placeholder {
  color: var(--vista-blue-1);
  opacity: 1;
}
.s-gate__plate:focus-visible {
  outline-offset: 0;
  background-color: var(--editorial-white-2);
}

/* --- Segment ------------------------------------------------------------
   A real fieldset. Its legend sits 16 above the first answer, and the two
   answers are 25 apart; the legend is taken out of flow so the flex column
   can own both gaps: 11 of cap height plus 16 is the 27 of padding.       */
.s-gate__seg {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--layout-gutter);
  margin: 0;
  padding: 27px 0 0;
  border: 0;
  min-inline-size: 0;
}
.s-gate__seg-legend {
  position: absolute;
  left: 0;
  top: 0;
  padding: 0;
  color: var(--content-on-brand);
}

/* Assessment_answer (741:4414) again, on the plate rather than in the panel:
   Pas Editorial White 4 with a Regular label, Act Amber 4 with an ExtraBlack
   one. The set carries no Hov variant, so hover and focus take the same 3px
   Amber ring the question panel uses.                                      */
.s-gate__opt {
  position: relative;
  display: flex;
  align-items: center;
  padding: 25px;
  background: var(--editorial-white-4);
  color: var(--content-primary);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, box-shadow var(--t-fast) ease;
}
.s-gate__opt:hover {
  box-shadow: inset 0 0 0 3px var(--action-border-hover);
}
.s-gate__opt:has(.s-gate__radio:checked) {
  background: var(--action-fill);
}
.s-gate__radio {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  appearance: none;
  opacity: 0;
  cursor: pointer;
}
.s-gate__opt:has(.s-gate__radio:focus-visible) {
  outline: 3px solid var(--border-accent);
  outline-offset: 2px;
}
.s-gate__opt-label {
  flex: 1 0 0;
  min-width: 0;
}

/* --- Button_form, 202 x 61 ---------------------------------------------- */
.s-gate__submit {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  border: 3px solid var(--action-fill);
  background: var(--action-fill);
  color: var(--content-on-accent);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.s-gate__submit:hover,
.s-gate__submit:focus-visible {
  background: var(--action-fill-hover);
  border-color: var(--action-border-hover);
}

/* ===== assessments/result.css ===== */
/* ==========================================================================
   Assessments — the verdict.  Intent tag: fluid.
   Figma: Assessments_P1 (741:5409), P2 (741:5739), P3 (741:5907).

   Every offset is a macket coordinate turned into a share of the working
   area (1340), so the block narrows with the page and holds its proportions.
   Macket x minus 50 gives the working-area coordinate.

     label     macket  164..366  ->  114..316  of 1340
     picture   macket  153..821  ->  103..771  of 1340   (668 wide)
       amber     macket 153..811 ->    0..658  of the 668
       author    macket 163..821 ->   10..668  of the 668
       panel     macket 391..821 ->  238..668  of the 668
     words     macket  846..1390 ->  796..1340 of 1340   (544 wide)

   The picture is the only thing in flow: its 668 x 822 ratio is what gives
   the block — and so the screen — its height.
   ========================================================================== */

.s-result[hidden] { display: none; }

.s-result__inner {
  position: relative;
}

/* --- Picture ------------------------------------------------------------ */
.s-result__art {
  position: relative;
  width: 49.8507%;               /* 668 / 1340 */
  margin-left: 7.6866%;          /* 103 / 1340 */
  aspect-ratio: 668 / 822;
}
.s-result__art[hidden] { display: none; }

.s-result__plate,
.s-result__author,
.s-result__silhouette {
  position: absolute;
  top: 0;
  height: 100%;
}

/* The studio panel the author stands against, macket 391..821. */
.s-result__plate {
  left: 35.6287%;                /* 238 / 668 */
  width: 64.3713%;               /* 430 / 668 */
  object-fit: cover;
}

/* The amber outline is the author's own alpha, painted 10px to her left and
   clipped by the mask group's rectangle. The file carries the shape only —
   the PNG is white pixels and nothing else — and the fill comes from the
   token, so the accent cannot drift from the rest of the page.            */
.s-result__silhouette {
  left: 0;
  width: 98.5030%;               /* 658 / 668 */
  background: var(--amber-4);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}
.s-result__silhouette--ready {
  -webkit-mask-image: url("../assets/assess-p1-silhouette.png");
  mask-image: url("../assets/assess-p1-silhouette.png");
}
.s-result__silhouette--sprint {
  -webkit-mask-image: url("../assets/assess-p2-silhouette.png");
  mask-image: url("../assets/assess-p2-silhouette.png");
}
.s-result__silhouette--grow {
  -webkit-mask-image: url("../assets/assess-p3-silhouette.png");
  mask-image: url("../assets/assess-p3-silhouette.png");
}

/* The cut-out author, macket 163..821 — real alpha, so the seven vertical
   lines and the page ground read through everywhere she is not.           */
.s-result__author {
  left: 1.4970%;                 /* 10 / 668 */
  width: 98.5030%;               /* 658 / 668 */
  object-fit: cover;
}

/* --- Label -------------------------------------------------------------- */
.s-result__label {
  position: absolute;
  z-index: 1;
  left: 8.5075%;                 /* 114 / 1340 */
  top: 0;
  width: 15.0746%;               /* 202 / 1340 */
  text-align: right;
}

/* --- Words --------------------------------------------------------------
   Five columns with their gutters, on the right margin. Title group 211,
   then 50, the lede, 50, and the button.                                   */
.s-result__words {
  position: absolute;
  z-index: 1;
  left: 59.4030%;                /* 796 / 1340 */
  top: 0;
  width: 40.5970%;               /* 544 / 1340 */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 50px;
}
.s-result__words[hidden] { display: none; }

/* The script word lies over the Mulish heading: cap top at 261, the
   heading's at 311. Padding and not a margin — a margin on the Mulish line
   collapses through this box and carries the script word down with it.    */
.s-result__title {
  position: relative;
  align-self: stretch;
  padding-top: 50px;
  font: inherit;
}
.s-result__script {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
}
.s-result__head {
  display: block;
}
.s-result__lede {
  align-self: stretch;
}

/* --- Button_form -------------------------------------------------------- */
.s-result__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  border: 3px solid var(--action-fill);
  background: var(--action-fill);
  color: var(--content-on-accent);
  cursor: pointer;
  transition: background-color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.s-result__cta:hover,
.s-result__cta:focus-visible {
  background: var(--action-fill-hover);
  border-color: var(--action-border-hover);
}
