/*
Theme Name: Audio Deluxe
Description: The storefront theme. A classic theme on the standard WooCommerce
             structure, which is the proven pattern in this segment - see
             docs/benchmark-dubaiaudio-stack.md. One theme serves all three
             storefronts; what differs between them is data, not markup.
Author: Audio Deluxe
Version: 0.1.0
Requires at least: 6.7
Requires PHP: 8.2
Text Domain: audiodeluxe
*/

/* Ported from the design repository's source/_head.html, painted with the brass
   palette — brass on bone, `/brass/` on the preview. Steel until 13 September
   2026; the change is recorded in DECISIONS.md. Do not edit the token values by hand: the design repository is where
   a palette is decided, and a value changed here and not there is a difference
   nobody can see until the two are compared. */

/* ============================================================
   1 · Tokens — the whole palette lives here.
   A dark section redefines six of them and nothing else.
   ============================================================ */
/* The overhang, declared as a length rather than left as a token. An
   unregistered custom property comes back from getComputedStyle as the text it
   was written as — `clamp(18px,2.4vw,38px)` — so the script that moves the
   planes used to read the number off some other property that happened to be
   set from it, and the right property differed per construction. Registered, it
   comes back resolved in pixels and there is one place to ask.

   It inherits: the plane is drawn on a pseudo-element, and a pseudo-element
   takes its custom properties from the element it hangs off. */
@property --plane{syntax:"<length>";inherits:true;initial-value:0px}
:root{
  --paper:#F4F0E8;          /* light section ground   */
  --night:#14110D;          /* dark section ground    */
  --white:#FFFFFF;          /* the second light ground */
  /* The plane a figure stands on when the section is white. Neutral rather
     than the paper, at the project owner's word of 23 September 2026: on
     white, the paper's warmth reads as a beige card behind the photograph
     instead of as a shadow of one, and what the plane is for is depth. */
  --plane-ground:#F0F0F0;   /* a figure's plane on white */
  /* The menu sheet's own ground. It is a palette value rather than one number
     for all three, because how much photograph may stay visible through it
     depends on what the palette's night is: a near-black one needs to be
     denser to read as a sheet at all.

     .92 since 13 September 2026, from .85. At .85 the page's own text showed
     through behind the menu's words on a phone and competed with them; a sheet
     you read a list on can afford to hide the page, and this one now does. The
     blur went up with it for the same reason — see .menu-panel. */
  --menu-ground:rgba(16,13,10,.92);
  /* How far the first menu level is lifted off the header bar. Zero is the
     construction the sheet started with - header and panel on one ground,
     reading as a single sheet. A lift separates them, and how much a palette
     needs is a palette question like the ground itself: the same white veil
     that is plainly visible over a warm near-black does almost nothing over a
     cold one. */
  --menu-lift:.05;
  /* The bar past the fold, as two values rather than as two stylesheets. A row
     that sits white and dims under the pointer, and a row that sits dim and
     brightens, are the same rule with these swapped — so which of the two a
     variant is stays a palette question, and the bar can be compared without a
     second copy of the header to compare it in. The logotype reads neither: it
     is white in the bar whichever way the row runs. */
  --bar-ink:#FFFFFF;
  --bar-ink-lift:rgba(255,255,255,.62);
  --ink:#1C1813;            /* text on paper          */
  --ink-dim:rgba(28,24,19,.66);
  --rule:rgba(28,24,19,.15);
  --brass:#9A7B4F;          /* accent                 */
  --brass-lift:#B08D57;
  --on-accent:#F4F0E8;
  --danger:#A93B3B;

  /* role tokens — components only ever read these */
  --bg:var(--paper);
  --fg:var(--ink);
  --fg-dim:var(--ink-dim);
  --line:var(--rule);
  --accent:var(--brass);
  --accent-fg:var(--on-accent);

  --display:"Cormorant Garamond",Georgia,"Times New Roman",serif;
  --ui:"Jost",system-ui,-apple-system,Segoe UI,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,Menlo,Consolas,monospace;

  --step-1:13.5px;
  --step0:16.5px;
  --step1:20px;
  --step2:clamp(29px,3.4vw,46px);
  --step3:clamp(52px,8.2vw,112px);

  /* One label style for every word in the header. The button was the one that
     read correctly, so it is the reference and the rest follows it. */
  --label-size:12px;
  --label-weight:500;
  --label-track:.16em;

  --gutter:clamp(20px,4.4vw,60px);
  --measure:60ch;
  --rhythm:clamp(56px,7.2vw,104px);
  /* The page's own edge, which is not the text column's. The masthead, the
     hero, the menu sheet and the footer all take the width of the page and stop
     at this margin; a column of text stops at --gutter, further in. The two were
     the same number written out in five places, which is how they came to differ
     by three pixels on a phone — the plate started at 23 and the paragraph under
     it at 20, and nobody chose that. */
  --edge:clamp(16px,5.9vw,124px);
  /* The hero plate's own margin, since 14 September 2026. The plate used to
     stand at --edge like everything else, and at a laptop's width that left a
     124px band of blurred backdrop either side of a photograph that is the
     whole reason the page exists. It now runs nearly to the window's edge — a
     hairline of backdrop, enough to say the plate is a plate and not the page —
     and the masthead, the menu sheet and the footer keep --edge above and
     below it. One number at every width: on a phone it was 16 and is now 15,
     which is the same reading. */
  --plate-edge:15px;
}

/* A second light ground, for the sections where the material is the subject
   rather than the words — the gallery and the document list. It is one role
   token, not a theme: ink, rules and accent on white are the same as on paper. */
.section--white{--bg:var(--white)}

/* the one inversion: a dark section swaps the role tokens */
.section--dark{
  --bg:var(--night);
  --fg:#FFFFFF;
  --fg-dim:rgba(255,255,255,.68);
  --line:rgba(255,255,255,.16);
  --accent:var(--brass-lift);
  --accent-fg:var(--night);
  background:var(--bg);
  color:var(--fg);
}

/* A dark section that is a lighter night — the same colour carried 15% of the
   way to white, applied over the dark modifier rather than instead of it — so
   it stands away from a dark neighbour. The brand page's range is drawn on it.
   Taken out on 14 September 2026 as unused when the landing's brand strip
   moved into the footer, and put back the same day: it was not. */
.section--dark.section--lift{--bg:color-mix(in srgb,var(--night) 85%,#fff)}

/* ============================================================
   2 · Base
   ============================================================ */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--ui);font-size:var(--step0);line-height:1.72;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block}
h1,h2,h3,h4,h5,h6,p,figure,ul,ol{margin:0}
ul{padding:0;list-style:none}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

.wrap{max-width:1240px;margin-inline:auto;padding-inline:var(--gutter)}
.display{
  font-family:var(--display);font-weight:300;letter-spacing:-.01em;
  font-optical-sizing:auto;text-wrap:balance;
}
h1.display{font-size:var(--step3);line-height:.95}
h2.display{font-size:var(--step2);line-height:1.1}
/* Capitals, as a modifier rather than as typed text — the field holds the
   sentence and the design decides how it is set. A serif in capitals needs
   the tracking opened slightly, or the letters read as one word. */
.display--caps{text-transform:uppercase;letter-spacing:.03em;line-height:1.16}
.kicker{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--accent);margin-bottom:14px;
}
p.body{color:var(--fg-dim);max-width:var(--measure)}
p.body + p.body{margin-top:16px}

/* ============================================================
   3 · Header — sits over the hero backdrop
   ============================================================ */
/* The header is fixed to the window rather than sitting in the hero, because it
   has to keep working after the hero has scrolled away. Which costs one thing:
   the room it used to take in the flow has to be given back to the hero by hand,
   and --mast-h is that number — its two paddings plus the logo. */
:root{--mast-h:clamp(122px,11.4vw,167px)}
/* The bar the header becomes once the page has scrolled, measured: 14px of
   padding either side of the logo. A link down the page — "Explore the
   series" to the range, an action to the enquiry — lands its target under
   this bar unless the target keeps that much clear, so every section carries
   it as its scroll margin. Since 16 September 2026, when the range's head
   went under the bar on every brand page. */
:root{--bar-h:75px}
.section,.band{scroll-margin-top:var(--bar-h)}
.masthead{
  position:fixed;inset:0 0 auto 0;z-index:50;padding-block:clamp(26px,2.6vw,46px);color:#fff;
  transition:background .5s ease,padding .5s ease,backdrop-filter .5s ease;
}
.hero{padding-top:var(--mast-h)}
/* One variant keeps the header the page had before it was fixed: laid over the
   photograph and scrolling away with it. Absolute rather than fixed, so the room
   the hero gives it is still right, and the script leaves it alone. It is the
   only structural difference between the three palettes, and it exists to be
   compared against the other two rather than to stay. */
.masthead--static{position:absolute}
/* Past the fold the header stops being a layer over a photograph and becomes a
   bar. Everything stays — the icons, the menu, the sections, the chip — and the
   whole row closes up onto one line. What changes is the logo: the name has
   already been read at the top of the page, and the bar follows the reader down
   it, so the mark alone is enough to get home by. The wordmark comes off.

   The drawing is one file and its two halves cannot be separated, so a half is
   exposed rather than extracted: the link becomes a window and the drawing is
   moved inside it. The fractions are measured, not guessed — the file is
   sixteen paths, fifteen of them the wordmark between 88.4% and 98.9% of the
   box, and the sixteenth the mark, running from 1.0% to 69.1%. The mark is the
   taller half, so it is the width that has to come down: at 60px the mark
   stands 24px, which is a bar's height rather than a hero's. */
.masthead.is-stuck{
  background:var(--night);padding-block:14px;
  /* The bar's own ink is a palette value; the name is not — it is white in both */
  color:var(--bar-ink);
}
.masthead.is-stuck .logo{color:#fff}
/* What the pointer does is stated once and read from the palette, so the two
   directions are one rule. The sections needed their own line — over a
   photograph they dim to .72 on hover, and that opacity would have held them at
   .62 here whatever the colour said. The chip does the same and takes a ground
   as well, because it is the one action in the row. */
.masthead.is-stuck .iconbtn:hover,
.masthead.is-stuck .menubtn:hover{color:var(--bar-ink-lift);opacity:1}
.masthead.is-stuck .sitenav a:hover{color:var(--bar-ink-lift);opacity:1}
.masthead.is-stuck .chip:hover{
  color:var(--bar-ink-lift);background:rgba(255,255,255,.14);border-color:var(--bar-ink-lift);
}
.masthead.is-stuck .logo-link{
  --logo-w:60px;--logo-h:calc(var(--logo-w) * 402 / 682);
  display:block;height:calc(var(--logo-h) * .681);overflow:hidden;
}
.masthead.is-stuck .logo--head{width:var(--logo-w);margin-top:calc(var(--logo-h) * -.01)}
/* Half a second, from .35 on 14 September 2026: the closing-up of the bar and
   the wordmark coming off happen together, and at .35 the pair read as a snap
   rather than a settle. The bar and the logo share the number so they still
   arrive at once. */
.logo--head{transition:width .5s ease}
@media (prefers-reduced-motion:reduce){
  .masthead,.masthead .logo--head,.masthead .nav-left,.masthead .nav-right{transition:none}
}
/* The header is white and only white, as in the reference. Which means the
   requirement moves to the material: the top of a slide has to be dark enough
   to carry it. That is a threshold to check when choosing photographs, not a
   mechanism to build. */
/* The header shares the plate's margins rather than the text container's, so
   the first icon and the plate's left edge stand on the same line.

   The side tracks are minmax(0,1fr) and not 1fr, which is the difference between
   a logotype that is centred and one that looks centred. A bare 1fr has auto as
   its minimum, so a side wider than its share pushes the middle column along
   instead of being made to fit — and the mark, which is the one thing on the
   page that has to sit on the centre line, ends up wherever the longest row of
   links leaves it. With a floor of zero the middle stays on the middle and it is
   the sides that have to be short enough. Which is the other half of this, and
   it is a content decision rather than a CSS one: see the row itself. */
.masthead .wrap{
  max-width:none;padding-inline:var(--edge);
  display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
  align-items:center;gap:28px;
}
.nav-left{display:flex;align-items:center;gap:22px}
/* The same gap the icons had when they were loose in the row, so wrapping them
   changes nothing at the widths where they are not moved. */
.tools{display:flex;align-items:center;gap:22px}
.nav-right{display:flex;justify-content:flex-end;align-items:center;gap:clamp(16px,1.8vw,28px)}

/* The language switch, in the row's own type rather than in a type of its own:
   it is one more word beside the sections, not a control.

   The header carries the language being read and nothing else. The others are
   stacked above and below it and come out under the pointer. The box keeps the
   room of one word, and the list inside it is taken out of the flow, so opening
   it moves nothing else in the row — a header that reflows when a pointer
   crosses it is a header that has to be caught.

   The list is slid so that the line of the language being read sits on the
   header's line: `--here` is which line that is, counted in PHP because it is
   the one thing the stylesheet cannot know. */
/* One of the two is drawn at any width. `display:none` rather than a visual
   hide, so the copy that is not in use is out of the accessibility tree and out
   of the tab order too. */
.langswitch--mob{display:none}
.langswitch{
  position:relative;
  font-family:var(--ui);font-size:var(--label-size);font-weight:var(--label-weight);
  letter-spacing:var(--label-track);text-transform:uppercase;line-height:1;
  width:2.7em;height:1em;
  --lang-line:2.1em;
}
.langs{
  position:absolute;left:0;top:50%;
  display:flex;flex-direction:column;align-items:flex-start;
  transform:translateY(calc((var(--here) + .5) * var(--lang-line) * -1));
}
.langs li{height:var(--lang-line);display:flex;align-items:center}
.langs a,.langs__here{white-space:nowrap;transition:opacity .25s ease}
.langs__here{opacity:1;transition:opacity .25s ease}
/* Shut: present in the box, not on the page. `visibility` rather than
   `display`, so the list keeps its height and the slide above stays true, and
   so the words are not in the tab order while they cannot be seen. */
.langs li:not(.is-here) a{opacity:0;visibility:hidden}
.langswitch:hover .langs li:not(.is-here) a,
.langswitch:focus-within .langs li:not(.is-here) a{opacity:.6;visibility:visible}
/* One word is white and the rest are grey, and which one is white follows the
   pointer. Shut, it is the language being read. Open with the pointer on
   another, that one takes the white and the language being read steps back to
   grey — because at that moment the reader is not asking what they are reading,
   they are looking at what they would get.

   The step back is stated on the box rather than on the word: a word cannot
   know that a different word is being pointed at, and `:has()` is how the box
   tells it. Where that is not understood the current language simply stays
   white, which is where this started. */
/* Written through the same chain the open state is written through. The rule
   that brings a word out — box hovered, word not the current one — carries four
   classes; `.langs a:hover` carries two, so the grey it sets was winning and
   the pointer changed nothing. Specificity is not a thing to be clever about
   here: the state that is more particular says so in the selector. */
.langswitch:hover .langs li:not(.is-here) a:hover,
.langswitch:focus-within .langs li:not(.is-here) a:focus-visible{opacity:1}
.langswitch:has(.langs a:hover) .langs__here,
.langswitch:has(.langs a:focus-visible) .langs__here{opacity:.55}

/* Where there is no pointer there is no hover, and a switch that only opens
   under one would be a switch nobody on a phone can reach. There the three
   stand in a row, which is what they were before this. */
@media (hover:none){
  .langswitch{width:auto;height:auto}
  .langs{position:static;flex-direction:row;align-items:center;gap:14px;transform:none}
  .langs li{height:auto}
  .langs li:not(.is-here) a{opacity:.6;visibility:visible}
}
/* 24px box against a 24-unit viewBox, so one user unit is one pixel and a
   stroke-width of 2 is exactly the 2px of the menu bars. Anything else and the
   icons and the bars are drawn at different weights. */
.iconbtn{
  width:24px;height:24px;color:currentColor;background:none;border:0;padding:0;
  cursor:pointer;
}
.iconbtn:hover{opacity:1}
.iconbtn svg{width:100%;height:100%;display:block}
/* The basket hangs two pixels low against the search icon beside it — its lid
   line reads as the top of the glyph, and that line sits below the circle's.
   The correction is on the glyph rather than on the button, so the 24px hit
   area stays where it was. */
.iconbtn--basket svg{transform:translateY(-2px)}
.menubtn{
  display:flex;align-items:center;gap:10px;background:none;border:0;padding:0;
  color:inherit;cursor:pointer;
  font-family:var(--ui);font-size:var(--label-size);font-weight:var(--label-weight);
  letter-spacing:var(--label-track);text-transform:uppercase;
}
.menubtn{white-space:nowrap}
/* Whole pixels only. A 1.5px rule cannot be drawn at a device ratio of 1, so
   each bar antialiases differently depending on where it lands in the grid and
   the three stop looking like three of the same thing. 3x2 + 2x4 = 14. */
.menubtn .bars{display:grid;gap:4px;width:20px;height:14px;align-content:start}
.menubtn .bars span{display:block;height:2px;background:currentColor;border-radius:0}
/* The three bars become a cross while the panel is open — the same control in
   two states rather than two controls. */
.menubtn .bars span{transition:transform .35s cubic-bezier(.22,.35,.03,1),opacity .2s}
.is-menu .menubtn .bars span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.is-menu .menubtn .bars span:nth-child(2){opacity:0}
.is-menu .menubtn .bars span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* ============================================================
   Г2 · The menu, as a sheet that comes down over the page

   It hangs off the header rather than off the page, so it follows the header
   when that closes up past the fold and needs no second measurement. It is
   glass, not a wall: the photograph stays visible through it, which is what
   keeps the page underneath rather than replaced. It is revealed by clipping —
   a transform would have to be masked, and there is nothing above it to mask
   against while the header is still transparent.
   ============================================================ */
.menu-panel{
  position:absolute;top:100%;left:0;right:0;
  /* The sheet's column measure, read by both of its bands. The sections above
     and the brand groups below are two grids of five over the same width, the
     same padding and the same gap, and a reader sees one set of columns rather
     than two — so a column that is narrower in one grid than in the other is
     not a taste, it is the two bands falling to different column counts at the
     same window width. They did: at 178px against 210px the brand groups broke
     to four while the sections still had five, anywhere from about 1180 to
     1390 CSS pixels — which is where a 14-inch Windows laptop at its
     recommended scale sits. One number, declared once, 22 September 2026. */
  --menu-col:178px;
  /* Two grounds, not one colour: the palette's sheet, and a white veil over it
     whose strength is the palette's own. Layered rather than mixed, so the
     ground stays the one value every other part of the menu reads. */
  background:linear-gradient(rgba(255,255,255,var(--menu-lift)),rgba(255,255,255,var(--menu-lift))),var(--menu-ground);
  -webkit-backdrop-filter:blur(28px) saturate(1.1);backdrop-filter:blur(28px) saturate(1.1);
  border-top:1px solid rgba(255,255,255,.1);
  border-bottom:1px solid rgba(255,255,255,.14);
  clip-path:inset(0 0 100% 0);visibility:hidden;
  transition:clip-path .55s cubic-bezier(.22,.35,.03,1),visibility 0s linear .55s;
  /* The sheet is never taller than the room under the header, and what does not
     fit is scrolled inside it. On a phone the columns stack and the sheet runs
     past the bottom of the window: without this the sections below the fold
     cannot be reached at all, and a finger dragged over them scrolls the page
     behind instead. The ceiling is written by the script, which measures that
     room; none is the fallback for the moment before it runs. `contain` keeps
     the drag from chaining to the page once the sheet reaches its end. */
  max-height:var(--panel-max,none);
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
}
/* While the sheet is open the page underneath is frozen rather than replaced:
   it keeps its scroll position and stops answering the scroll, so the only
   thing that moves is the sheet. Stated on both elements because either one of
   them can be the scrolling box, depending on the browser. */
html.is-menu-open,html.is-menu-open body{overflow:hidden;overscroll-behavior:none}
.masthead.is-menu .menu-panel{
  clip-path:inset(0 0 0 0);visibility:visible;transition-delay:0s,0s;
}
/* While it is open the header takes the same ground, so the two read as one sheet */
.masthead.is-menu{background:var(--menu-ground);-webkit-backdrop-filter:blur(28px) saturate(1.1);backdrop-filter:blur(28px) saturate(1.1)}
.menu-panel__inner{
  max-width:none;padding:clamp(30px,4vw,60px) var(--edge) clamp(36px,4.6vw,72px);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--menu-col),1fr));gap:clamp(22px,3vw,54px);
}
/* Every heading in the sheet is set at one size — this one, the brands band's,
   and the group labels inside it. They are read against links now all set at
   the same size too, and a sheet whose labels differ by a point or two states a
   ranking its content does not have. */
.menu-col h3{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:rgba(255,255,255,.5);margin-bottom:16px;
}
.menu-col a{
  display:block;font-family:var(--display);font-weight:300;font-size:clamp(20px,1.6vw,26px);
  line-height:1.55;color:#fff;transition:color .2s,padding-left .3s;
}
.menu-col a:hover{color:var(--brass-lift);padding-left:6px}
/* The brands band, under the columns and inside the same sheet. Lighter, and
   at the same transparency: a white veil laid over the ground rather than a
   second, paler ground — mixing the palette's own colour towards white would
   have moved its alpha with it, and how much photograph stays visible through
   this sheet is a palette decision already taken. The blur is the sheet's; this
   only tints what is already there. */
/* Closed until it is asked for. Opening the menu and being handed both bands at
   once says the sixteen brands are as important as the five sections, and they
   are not — they are what one of the fifteen links leads to. So the band is a
   row of no height until All brands is pressed, and it opens under the link that
   named it. The ground and the rule live on the inner box rather than on this
   one: an outer box that is only a clip would otherwise still draw its own
   border while there is nothing inside it to see. */
.menu-brands{
  /* max-height and not a zero row. A collapsing grid row is the tidier of the
     two, but it only collapses while the item inside it is allowed a minimum of
     nothing — and that condition is easy to satisfy and easier to lose, because
     it depends on a property of the child rather than on anything written here.
     A clipped box with no height has no such condition. The ceiling is a number
     large enough for the band and never reached, so what is animated is the
     clip, not the content. */
  overflow:hidden;max-height:0;
  transition:max-height .5s cubic-bezier(.22,.35,.03,1);
}
/* The open height is written by the script, and it is the band's own — the
   whole of it, never a fraction of the window. What keeps a tall band reachable
   on a short one is the sheet around it, which is the single scrolling box: a
   band that scrolled inside a sheet that also scrolled would be two of them
   nested, and on a touch screen the wrong one takes the drag. That is how All
   brands became unreachable on a phone. 70vh is only the fallback for the
   moment before the script runs. */
.masthead.is-brands .menu-brands{max-height:70vh}
/* On a phone the second level takes the sheet. The five columns are taller than
   the window there, so with them in front the band opened below the fold and
   could not be scrolled to the top either — it is the last thing in the sheet,
   and a scroll cannot go past the end of what it scrolls. Put away, the band is
   the first thing under the collapsed masthead, which is where it was asked for
   on 24 September 2026.
   They come back when the band closes, and the way out of both is the same X
   that was always there. Not above 700: a narrowed window on a desktop is not a
   phone, its sheet has room for both levels, and the scroll in site.js lifts the
   band there instead.

   One rule and no second one raising the band's ceiling: the open height is the
   script's own inline number, measured after the columns have gone, so the band
   is already as tall as it needs to be and the sheet around it scrolls. */
@media (max-width:700px){
  .masthead.is-brands .menu-panel__inner{display:none}
}
@media (prefers-reduced-motion:reduce){.menu-brands{transition:none}}
.menu-brands__inner{
  background:rgba(255,255,255,.06);
  border-top:1px solid rgba(255,255,255,.1);
  padding:clamp(24px,2.6vw,40px) var(--edge) clamp(28px,3vw,52px);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));
  gap:2px clamp(22px,3vw,54px);
}
.menu-brands__inner h3{
  grid-column:1/-1;
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:rgba(255,255,255,.5);margin-bottom:14px;
}
/* A brand name is set exactly as a section link: same face, same weight, same
   size, same white, same leading. It was a shade smaller and a shade dimmer,
   on the reasoning that sixteen brands must not weigh as much as five sections
   — but three weakenings in the same direction do not read as one step down a
   hierarchy, they read as a second-class list, and these are the names the
   sheet exists to carry. The hierarchy is already stated by where the band is:
   it is shut until All brands is pressed, and it opens underneath the link that
   asked for it. Position says it once; the type does not have to say it again. */
.menu-brands__inner a{
  display:block;font-family:var(--display);font-weight:300;
  font-size:clamp(20px,1.6vw,26px);line-height:1.55;color:#fff;
  transition:color .2s,padding-left .3s;
}
.menu-brands__inner a:hover{color:var(--brass-lift);padding-left:6px}
@media (prefers-reduced-motion:reduce){.menu-brands__inner a{transition:none}}
/* The A-Z band on a wide screen, and only there. auto-fit puts in as many
   columns as fit, which at 2400px is ten - sixteen names scattered over a row
   and a third, with the second row two thirds empty. Four columns is sixteen
   over four rows exactly, and it is four whatever the screen does past this
   width. Narrower than 1600 the auto-fit is left alone: there the column count
   is a real constraint rather than a runaway, and it already reads correctly.

   Flow stays across rather than down. The heading spans the full row - it is
   grid-column 1/-1 - and a spanning item and column flow do not coexist: the
   names would start in the second row of the first column and run off the end
   of the grid. Reading an alphabet down a column would be better; it is not
   worth restructuring the markup of both bands to get it. */
@media (min-width:1600px){
  .menu-brands--az .menu-brands__inner{
    grid-template-columns:repeat(4,minmax(0,1fr));
  }
}

/* Two arrangements of one band, and a page shows one of them. Which one is a
   class on the header, set by the build the same way the static header is —
   the difference is worth looking at, not worth a second menu. */
.menu-brands--type{display:none}
.masthead--brands-type .menu-brands--az{display:none}
.masthead--brands-type .menu-brands--type{display:block}
/* Closed is stated twice, and on purpose. The attribute is the state — it is in
   the markup before a stylesheet or a script has had a say, so the band is shut
   on a page that never runs either. The clipped height is only how it opens. A
   variant that has to say `display:block` to choose between the two bands would
   otherwise be one line away from overriding the browser's own meaning of
   hidden, and the failure would look like a design decision rather than a fault. */
.menu-brands[hidden]{display:none}
/* The type band is not itself the grid: the heading stands above one. A heading
   inside the grid spanning every column is the ordinary arrangement, and it is
   what kept this band from lining up with the sections above — see the note in
   header.php. */
.menu-brands__inner--type{display:block}
.menu-brands__inner--type h3{margin-bottom:20px}
.menu-groups{
  display:grid;
  /* The section columns' own measure and the section columns' own gap, so that
     the two bands are one set of columns read top to bottom rather than two
     that happen to be near each other. Both collapse to the five they carry,
     and both break to four, three and two at the same window widths. */
  grid-template-columns:repeat(auto-fit,minmax(var(--menu-col),1fr));
  /* Down, the only thing under a group's heading is that heading's own subject,
     so the space there is a heading's space rather than a column's. */
  gap:20px clamp(22px,3vw,54px);align-items:start;
}
.menu-group h4{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.18em;
  text-transform:uppercase;color:var(--brass-lift);margin-bottom:10px;
}
@media (prefers-reduced-motion:reduce){
  .menu-panel,.menubtn .bars span,.menu-col a{transition:none}
}
.logo{display:block;color:currentColor;shape-rendering:geometricPrecision}
/* In the fixed header the section row is hidden until it has been measured to
   fit; the other composition puts its whole navigation in this element, so it
   is never hidden there. Default off rather than default on, because the wrong
   way round is a header that jumps on load, and the wrong way round with no
   JavaScript at all is a logotype permanently off its centre. */
.masthead:not(.masthead--light) .sitenav{display:none}
.masthead.is-wide:not(.masthead--light) .sitenav{display:flex}
.sitenav{display:flex;gap:26px}
.sitenav a{
  font-family:var(--ui);font-size:var(--label-size);font-weight:var(--label-weight);
  letter-spacing:var(--label-track);text-transform:uppercase;white-space:nowrap;
  transition:opacity .2s;
}
.sitenav a:hover{opacity:.72}
@media (max-width:1180px){.sitenav{display:none}}
.logo--head{width:clamp(118px,8vw,153px);height:auto;aspect-ratio:682/402;margin-inline:auto}
.chip{
  border:2px solid rgba(255,255,255,.62);padding:11px 20px;white-space:nowrap;
  font-family:var(--ui);font-size:var(--label-size);font-weight:var(--label-weight);
  letter-spacing:var(--label-track);text-transform:uppercase;
  transition:background .2s,border-color .2s;
}
.chip:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.75)}
/* Below 700 the header is two rows. Measured at 360: the chip wants 186px, the
   mark 118, the icons and MENU 71 — 375 of gap-free content into 360 of window,
   so the three of them cannot share a line however the tracks are written, and
   what actually happened was the chip printing over the logotype.

   The call to action takes a line of its own, full width, and the bar below it
   keeps the three columns it has at every other size — which is the reference's
   own answer at this width, and the reason it is right is that the mark stays on
   the centre line. Squeezing instead would have cost either the mark's centre or
   the button, and the button is the page's one instruction.

   --mast-h is stated again because it is the room the hero gives back by hand:
   26 + 47 + 14 + 70 + 26. A second row is 61px of it. */
@media (max-width:700px){
  /* Less air around everything on a phone. The desktop measures are proportions
     of a wide window and they were being read as generosity on a 390px one:
     23px of margin either side takes 12% of the screen before a photograph
     starts, and 56px above and below each section is a third of the fold spent
     on nothing.

     The two side measures also become one. On a page this narrow the difference
     between the text column and the page edge has nothing left to say — there is
     one column — so the plate, the paragraph under it and the footer all stop on
     the same line, which is the thing the eye actually reads as tidy.

     They step at the breakpoint rather than easing into it. Nobody crosses 700
     on a phone; the only reader who sees the step is one resizing a desktop
     window, and the alternative is a formula tuned to make an invisible
     transition smooth. */
  :root{--mast-h:183px;--bar-h:113px;--gutter:16px;--edge:16px;--rhythm:clamp(40px,10vw,56px)}
  .masthead .wrap{
    grid-template-areas:"cta cta cta" "left logo right";
    row-gap:14px;column-gap:12px;
  }
  /* The row's own box goes away and its children become items of the header's
     grid, which is the only way one of them crosses to the other side of the
     mark. Nothing is duplicated and no second markup exists for the phone. */
  .nav-left{display:contents}
  .menubtn{grid-area:left;justify-self:start}
  /* Both sides stand on the button's edges rather than near them: the menu
     starts where REQUEST AUDITION starts and the icons end where it ends, so
     the header reads as two lines of one block instead of two rows that were
     centred separately. */
  .tools{grid-area:right;justify-self:end}
  .logo-link{grid-area:logo}
  .nav-right{grid-area:cta}
  /* The call to action has the row to itself at this width, and the language
     switch leaves it: on a phone it stands after the search icon, with the
     other things a reader taps rather than reads. */
  .langswitch--desk{display:none}
  .langswitch--mob{display:block}
  .tools{display:flex;align-items:center;gap:18px}
  .chip{display:block;width:100%;text-align:center}

  /* The open sheet is read at arm's length on a phone, not at a desk, and every
     size in it is already sitting on its floor: below 1250px the two clamps have
     nothing left to give and resolve to their minimum, so the panel a phone gets
     is the smallest the design ever draws. A point on the links and one on the
     headings is the smallest step that reads, and it is spent here rather than
     in the clamps, where it would also move every window between a phone and a
     desktop that the design already answers correctly. */
  .menu-col a,
  .menu-brands__inner a{font-size:21px}
  .menu-col h3,
  .menu-brands__inner h3,
  .menu-group h4{font-size:13.5px}
}


/* ============================================================
   4 · Hero — two layers: full-bleed backdrop, contained plate
   ============================================================ */
/* The hero is as tall as its parts, not as tall as the window. The plate keeps
   its own proportion, the floor below it is added rather than subtracted, and
   the whole thing overruns the fold — which is what makes the page ask to be
   scrolled. */
.hero{
  position:relative;overflow:hidden;background:var(--night);
  display:flex;flex-direction:column;
  /* How far the backdrop is lifted towards white. One value, read by the script
     as well, so the measurement and the lift cannot drift apart. */
  --bd-lift:.10;
}
/* The lift cannot be a filter: brightness() is a multiplication, and a black
   photograph multiplied by 1.1 is still black — which is exactly the case this
   exists for. It is a flat white veil instead, over both backdrop layers and
   under the plate, the masthead and the controls. */
.hero::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:#fff;opacity:var(--bd-lift);
}
/* The backdrop is the photograph itself at maximum blur. Its tonal range is
   what gives the page its colour, so nothing is laid over it to even it out —
   every scrim in this hero lives inside the plate instead. */
.hero__backdrop{
  /* Same framing as the plate, only larger — the plate is a window cut into
     this. The element is grown by roughly two blur radii so the blur has
     material to sample at the edges; any more than that and the backdrop stops
     lining up with the picture inside the plate. No transform: a scale would
     zoom the backdrop out of register again. */
  position:absolute;inset:-60px;
  /* Not cover: cover crops the picture to the shape of the window, and the
     window is not the shape of the plate — which is what put the two out of
     register. Stretched to fill instead, so the backdrop and the plate show the
     same frame from edge to edge. The distortion this costs is invisible under
     the blur; the alignment it buys is not. */
  background-size:100% 100%;background-position:center;
  /* The backdrop keeps the photograph its own colour, with nothing added. It is only
     pulled down when the photograph itself would put the white header at risk.
     How far down is measured per picture, not guessed once for all of them —
     see the script. A dark photograph is never touched. */
  filter:blur(45px) brightness(var(--bd-dim,1));
  opacity:0;transition:opacity 1.5s cubic-bezier(.22,.35,.03,1);
}

/* Two of them, alternating: the incoming photograph is loaded into whichever
   layer is hidden and then faded up, so the page's colour changes with the
   slide instead of jumping. */
.hero__backdrop[data-show]{opacity:1}
@media (prefers-reduced-motion:reduce){.hero__backdrop{transition:none}}
.hero__stage{
  position:relative;z-index:2;display:flex;
  width:100%;
  /* The floor under the plate is the same hairline as the sides — asked for
     on 20 September 2026, once the plate had become the first screen exactly.
     Until then it was about three times the side margin, as the drawing had
     it, so the backdrop showed under the plate; with the plate ending at the
     window's edge that floor was three times the sides for no reason the eye
     could find. */
  padding:0 var(--plate-edge) var(--plate-edge);
}
/* pan-y is what makes the drag possible at all: it hands the browser the
   vertical gesture, which is the page scrolling, and keeps the horizontal one,
   which is the slider. Without it the browser claims both and cancels the
   pointer stream halfway through every swipe. */
.plate{position:relative;width:100%;aspect-ratio:2.3/1;overflow:hidden;display:flex;touch-action:pan-y}
/* The landing's plate is the first screen, caption and all — no more and
   no less. Asked for on 20 September 2026, twice: first when a 23-inch
   monitor (1920 wide, some 950 tall inside the browser) cut the caption off
   under the fold, then when the 14-inch Mac — the reference screen — showed
   twenty pixels of the next section under the hero. So the plate's height
   is the window's, less the masthead and the floor: it keeps the page's
   full width and the photograph is cropped to the box, held at its own
   focus — top and bottom on a 16:9 monitor, where the plate comes out
   nearer 2.6:1, a sliver at the sides on a 16:10 laptop, where it is a
   little taller than 2.3:1. The floor guards a very short window, where a
   plate 200px tall would be a strip, not a stage; it is set under what a
   14-inch Windows laptop at 150% leaves (1280 × 640 inside the browser:
   457px), so that screen too gets exactly one screen. The ceiling, 2:1,
   guards a tall window. Not below 1080 wide, where the plate has its own
   proportions and a phone has its own height rules. */
@media (min-width:1081px){
  .hero--landing .plate{height:clamp(400px,calc(100svh - var(--mast-h) - var(--plate-edge)),50vw)}
}
/* The third standard, for a tablet held upright — 21 September 2026. Between
   the phone and the desktop the plate kept its 2.3:1, which on an iPad in
   portrait (820 × 1180) is a 343px strip at the top of a screen three times
   that tall. Here too the plate is one screen — the window's height less the
   masthead and the floor — and the picture is the tall cut, which the
   <picture> in inc/hero.php and the clip in site.js switch to under the same
   query. The ceiling, 1.35 times the width, is a shade over the tall cut's
   own 4:3, so no window makes the plate taller than the picture it holds;
   the floor is the 2:1 the brand hero takes at this width. A tablet on its
   side is wider than 1080 or nearly, and keeps the desktop's rule or the
   2.3:1 plate, both of which fit one screen there. */
@media (min-width:701px) and (max-width:1080px) and (orientation:portrait){
  .hero--landing .plate{height:clamp(50vw,calc(100svh - var(--mast-h) - var(--plate-edge)),135vw)}
}
/* And the fourth, a tablet on its side — the same day. An iPad in landscape
   is 1024 to 1366 wide and 768 to 1024 tall: below 1081 it had the 2.3:1
   plate, 445px of a 768px screen, and above it the desktop's rule, whose
   50vw ceiling — there to guard a tall desktop window — held the plate to
   590px of an 820px screen. Here the plate is one screen with the ceiling
   let out to 62vw, which no tablet reaches. Told apart from a desktop
   window of the same size by the pointer: a laptop at 1366 × 768 keeps the
   desktop's rule, a tablet has no fine pointer and takes this one. The
   picture stays the wide cut, as on a desktop. */
@media (min-width:701px) and (max-width:1366px) and (orientation:landscape) and (pointer:coarse){
  .hero--landing .plate{height:clamp(400px,calc(100svh - var(--mast-h) - var(--plate-edge)),62vw)}
}
}
/* A photograph is a thing a mouse drags by default, and that native drag lands
   in the middle of the same gesture. */
.plate picture img{-webkit-user-drag:none;user-select:none}
/* The brand page's hero is the same construction at a different proportion, and
   the difference is what the page is for. The landing's plate is a stage: it is
   the whole reason to stop, and seven photographs take turns on it. A brand page
   is reached by someone who has already chosen the brand, so its picture is a
   title band rather than a stage — 4.8:1 instead of 2.3:1, which is 350px rather
   than 730 at the page's own measure, and the range is on the screen instead of
   under it. It is the height that comes off and not the width: a band that
   narrowed at the sides would stop being full-bleed, and full-bleed is what
   makes it a band rather than a picture in a column. The backdrop stays: it is what the white header sits over, and that
   is true at any height. */
.hero--brand .plate{aspect-ratio:4.8/1}
.hero--brand .hero__stage{padding-bottom:clamp(14px,1.7vw,28px)}
/* The caption is bottom-anchored, so where it sits in the band is its own
   bottom padding and nothing else. On a 4.8:1 band the landing's measure leaves
   the row floating with a strip of photograph under it; halved, the row sits
   down on the band's floor the way a title does. The sides and the top keep the
   landing's measure — it is the height that changed, not the plate. */
.hero--brand .plate__caption{padding-bottom:clamp(12px,1.5vw,22px)}
/* The caption stacks at 1080px — mark, sentence, button one under the other —
   and stacked it is some 270px tall, which a 4.8:1 band is not until the page
   is 1300px wide. Between the stacking and the phone the band was shorter than
   its own caption, and the mark climbed out of the picture into the header
   (19 September 2026, at 800 and 950px). So where the caption stacks the band
   takes 2:1 — 330px at 700, 520px at 1080 — and the caption sits inside it
   again; the phone below keeps its 4:5 and its own picture. */
@media (max-width:1080px){.hero--brand .plate{aspect-ratio:2/1}}
@media (max-width:700px){.hero--brand .plate{aspect-ratio:4/5}}
.slides{position:relative;width:100%;height:100%}
/* The incoming photograph enters from the side you asked to go towards, and
   the outgoing one leaves the other way — press the right arrow and the next
   picture arrives from the right. */
.slide{
  position:absolute;inset:0;margin:0;visibility:hidden;
  transform:translateX(100%);
  /* A short pull away, then a long settle. The curve spends most of its time
     slowing down, which is what stops the change reading as a jump. */
  transition:transform 1.5s cubic-bezier(.22,.35,.03,1);
  will-change:transform;
}
.slide.is-on{visibility:visible;z-index:2;transform:translateX(0)}
.slide.is-off{visibility:visible;z-index:1}
/* The slide's own photograph, and only that. `.slide img` catches every image
   inside the slide, and a brand hero puts the manufacturer's logotype in the
   caption — which then took width 100%, height 100% and object-fit cover, and
   filled the plate. The picture is always inside <picture>; nothing else in a
   caption ever is. */
.slide picture img{
  width:100%;height:100%;object-fit:cover;
  /* Each photograph has its own subject, so each says where to hold on to when
     the box is cropped. Without this the speaker drifts out of frame as soon as
     the window is a different shape from the file. */
  object-position:var(--focus,center);
}
/* Every slide keeps moving after it has arrived. Not a loop and not a drift:
   it begins where the slide settles, closes six per cent over seven seconds and
   stops there — a photograph that comes to rest rather than one that is still
   going when the reader looks away.

   The scale is on the picture, not on the slide. The slide's transform is how
   the carousel carries it across, and two transforms on one element is one of
   them overwriting the other.

   It starts a beat and a half in, which is the length of the arrival — the move
   and the zoom overlapping would read as one long move, and the point of this is
   that it happens to a picture that has already stopped. The outgoing slide is
   left at the size it reached: releasing it would snap the photograph back while
   it is still on screen. */
.slide.is-on picture img{
  /* The curve matters more here than the duration does. The page's usual easing
     spends itself early — it is drawn for a move that has to feel decisive — and
     at seven seconds that reads as three of movement and four of nothing. This
     one holds its second control point back to 0.75, so the picture is still
     closing at six seconds and only then settles. */
  animation:slide-close 7s 1.5s cubic-bezier(.35,.05,.75,1) forwards;
}
.slide.is-off picture img{transform:scale(1.06)}
@keyframes slide-close{from{transform:scale(1)}to{transform:scale(1.06)}}
/* A slide's clip lies over its photograph, cut the same way and held at the
   same point, so the frame it opens on and the still under it are one picture.
   It does not take the close: it is already moving, and a zoom on top of the
   manufacturer's camera would be two cameras. Under the veil and the caption,
   which follow it in the document. On a phone it is there only if it has a
   tall cut of its own — a clip without one is not shown there at all: the
   slide's tall photograph is the slide, and the script never asks the clip to
   load. */
.slide__clip{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:var(--focus,center);
  pointer-events:none;
}
@media (max-width:700px), (max-width:1080px) and (orientation:portrait){.slide__clip:not([data-src-tall]){display:none}}
@media (prefers-reduced-motion:reduce){
  .slide{transition:none}
  .slide.is-on picture img,.slide.is-off picture img{animation:none;transform:none}
  .slide__clip{display:none}
}
/* Two independent scrims at the top: a gradient falling from the edge, and an
   even mat behind each control cluster. The bottom one is a gradient rising
   from the floor, behind the caption. */
.plate__top{
  position:absolute;inset:0 0 auto 0;height:190px;pointer-events:none;z-index:3;
  background:linear-gradient(180deg,rgba(0,0,0,.5) 0%,rgba(0,0,0,.16) 55%,rgba(0,0,0,0) 100%);
}
/* Above the slides: the active one carries a stacking order of its own, so the
   controls have to say where they sit or the photograph covers them. */
.plate__controls{
  position:absolute;inset:0 0 auto 0;z-index:4;display:flex;justify-content:space-between;
  align-items:flex-start;padding:clamp(16px,2vw,26px);gap:20px;
}
.control-mat{
  background:rgba(0,0,0,.42);padding:9px 15px;display:flex;align-items:center;gap:14px;
}
.count{
  font-family:var(--ui);font-size:var(--label-size);font-weight:var(--label-weight);
  letter-spacing:var(--label-track);color:#fff;font-variant-numeric:tabular-nums;
}
/* Every slide gets a mark: a dot for the ones not showing, a dash for the one
   that is. It reads as position in a loop rather than progress towards an end,
   and it does not care how many slides there are — which matters, because the
   number is not fixed. */
.dots{display:flex;align-items:center;gap:9px}
.dot{
  display:block;width:6px;height:6px;padding:0;border:0;border-radius:50%;
  background:rgba(255,255,255,.5);cursor:pointer;
  transition:width .9s cubic-bezier(.22,.35,.03,1),height .9s cubic-bezier(.22,.35,.03,1),
    border-radius .9s ease,background .3s ease,opacity .3s ease;
}
.dot:hover{background:rgba(255,255,255,.8)}
.dot[data-active]{
  width:18px;height:4px;border-radius:2px;background:#fff;cursor:default;
}
@media (prefers-reduced-motion:reduce){.dot{transition:none}}
/* Each arrow carries its own mat, with air between them — one mat around both
   reads as a single control rather than two. */
.arrows{display:flex;align-items:center;gap:8px}
.arrowbtn{
  width:36px;height:36px;display:grid;place-items:center;border:0;
  background:rgba(0,0,0,.42);color:#fff;cursor:pointer;
  transition:background .2s;
}
.arrowbtn:hover{background:rgba(0,0,0,.66)}
.arrowbtn svg{width:22px;height:22px;display:block}
/* On a phone the arrows come off and the picture is dragged instead. A 36px
   target beside another one in the top corner of a photograph is a miss waiting
   to happen, and a picture that can be swiped does not need a button saying so
   — the named reference drops them at this width as well. The marks stay: they
   say how many there are and where this one sits, which dragging does not tell
   anybody.

   The swipe is not a stand-in for the missing arrows. It works at every width;
   below this one it is simply the only thing there is, which is why the two
   changes belong together. */
@media (max-width:700px){.arrows{display:none}}
.plate__veil{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,.88) 0%,rgba(0,0,0,.42) 30%,rgba(0,0,0,0) 62%);
}
/* Inside the plate the ground is a photograph, so this is a dark context and
   says so — the buttons and rules then take their colours from the same tokens
   as any other dark section, instead of inheriting the light section's accent. */
.plate__caption{
  --fg:#FFFFFF;
  --fg-dim:rgba(255,255,255,.8);
  --line:rgba(255,255,255,.34);
  --accent:var(--brass-lift);
  --accent-fg:var(--night);
  position:absolute;inset:auto 0 0 0;padding:clamp(22px,3.2vw,46px);
  display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr) auto;
  gap:clamp(20px,3vw,54px);align-items:end;color:var(--fg);
}
.plate__caption h1{color:var(--fg);margin:0}
/* The three stand on one line at the foot: the name's letters, the last line
   of the sentence and the bottom edge of the buttons. The grid already aligns
   the boxes to their end, but a text box reaches below its letters — half a
   line's leading and the descender space — so the name and the sentence sat
   visibly higher than the buttons beside them. The box is trimmed to the
   alphabetic baseline at its end instead, so the box's bottom is the
   letters' bottom and the grid's alignment is the eye's. Where a browser does
   not know text-box yet, the line is what it was on 16 September 2026. */
.plate__caption h1,.plate__caption p{text-box-trim:trim-end;text-box-edge:cap alphabetic}
/* The sentence takes its column — the whole width between the name and the
   buttons — standing on one line wherever it fits and wrapping only where
   the column itself runs out. Until 19 September 2026 a 52ch measure held
   every caption to two lines; the brand hero dropped it that day, since on a
   band 350px tall a second line is a third of the height, and on 20
   September the landing's slides were asked to follow the brand page. */
.plate__caption p{color:var(--fg-dim);font-size:15.5px;line-height:1.6}
.plate__actions{display:flex;gap:11px;flex-wrap:wrap;justify-content:flex-end}
/* On a phone the two run full width, one under the other. Wrapping already put
   them on two lines; what it could not do is make them the same width, and two
   buttons of different lengths stacked left read as one instruction and one
   afterthought rather than as a choice. Full width also gives the thumb the
   whole line to land on. */
@media (max-width:700px){
  .plate__actions{flex-direction:column;align-items:stretch;gap:10px}
  .plate__actions .button{width:100%;text-align:center}
  /* The landing's slides say only their name on a phone: on a 3:4 plate the
     sentence is four lines, under a name and over a button, on a photograph
     that was chosen to be looked at. Since 17 September 2026. The brand and
     page heroes keep theirs — one sentence, no slider, and the page is that
     brand's. */
  .hero--landing .plate__caption p{display:none}
}
.plate__caption .button--ghost{
  color:#fff;border-width:2px;border-color:rgba(255,255,255,.72);background:rgba(0,0,0,.25);
}
.plate__caption .button--ghost:hover{background:rgba(255,255,255,.14);color:#fff}

/* ============================================================
   Slide caption variants — six pairings, one per slide, so a
   choice can be made from the page rather than from a
   description. Each variant sets two things: how the buttons are
   drawn, and how the heading and its paragraph sit together. The
   heading comes down from the hero size in every one of them —
   at 112px the paragraph beside it reads as an afterthought.
   These are numbered by slide, not named, and five of the six go
   away once one is chosen.

   The actions are chosen, 17 September 2026: every slide draws the
   third variant's — outlined at a hairline, nothing filled, white
   inside an accent line. The rules sit on `.slide` so a treatment says
   nothing about its buttons any more; what the six still differ in is
   the heading and the paragraph. The brand and page heroes were
   already on the third variant, so the site now has one hero button.
   Later the same day the second action — accent inside a white line,
   the shop's — came off every hero until there is a shop; its rule
   stays for the day it comes back.
   ============================================================ */
/* The hero's outlined button: transparent, the accent's own hairline, and its
   own tracking and padding, which are wider than the solid button's.
   `.eventback` joins it on 23 September 2026 — the project owner asked for the
   Crystal Cable slide's button, exactly, under an event's reading. One rule for
   both rather than a copy under the events section, so the two cannot drift. */
.slide .button,
.eventback .button{
  background:transparent;border:1px solid var(--accent);color:#fff;
  letter-spacing:.24em;padding:15px 30px;
}
.slide .button:hover{background:rgba(255,255,255,.1);color:#fff;border-color:#fff}
.slide .button--ghost{
  border-width:1px;border-color:rgba(255,255,255,.6);background:none;color:var(--accent);
}

/* 1 · Heading a third smaller than the hero size, the paragraph a touch
       dimmer. */
.slide--v1 h1{font-size:clamp(44px,6.2vw,84px);line-height:.98}
.slide--v1 .plate__caption p{font-size:16.5px;color:rgba(255,255,255,.86)}

/* 2 · A smaller heading and a looser paragraph. */
.slide--v2 h1{font-size:clamp(40px,5.4vw,72px);line-height:1.02}
.slide--v2 .plate__caption p{font-size:17px;line-height:1.65}

/* 3 · The paragraph set in the display serif — larger, and easier over a
       photograph than 15.5px of sans. Its actions are now every slide's,
       above. */
/* The heading takes slide 4's typeface — the interface sans, light, spaced and
   set in capitals — while everything else about this variant stays its own: the
   paragraph in the serif and the hairline outlines around the actions. */
.slide--v3 h1{
  font-family:var(--ui);font-weight:300;font-size:clamp(32px,4.1vw,54px);
  letter-spacing:.04em;line-height:1.1;text-transform:uppercase;
}
.slide--v3 .plate__caption p{
  font-family:var(--display);font-size:19px;line-height:1.45;
  color:rgba(255,255,255,.92);
}

/* 4 · The heading changes typeface — the interface sans, light, spaced. */
.slide--v4 h1{
  font-family:var(--ui);font-weight:300;font-size:clamp(32px,4.1vw,54px);
  letter-spacing:.04em;line-height:1.1;text-transform:uppercase;
}
.slide--v4 .plate__caption p{font-size:16.5px;color:rgba(255,255,255,.84)}

/* 5 · The paragraph carries a shadow, because this slide is the bright one. */
.slide--v5 h1{font-size:clamp(38px,5vw,66px);line-height:1.02}
.slide--v5 .plate__caption p{font-size:17px;text-shadow:0 1px 14px rgba(0,0,0,.55)}

/* 6 · The white sweep read the other way: ink on paper instead of white on a
       darkened picture. The veil rises white rather than black. */
/* Half the height it had, since 23 September 2026. The caption reaches 28 per
   cent up from the plate's foot at its tallest — on a phone and on the short
   1280 × 640 laptop, where it stacks — and the veil was fading out at 66, which
   is twice what it covers and the reason the packshot had to be lifted so far
   clear of it. Out by 34 now, a margin of six points over the tallest caption
   there is, and the product comes back down by the same amount. The dark veil
   above is untouched: this slide is the only one drawn on v6, and the others
   stand on photographs that need every point of it. */
.slide--v6 .plate__veil{
  background:linear-gradient(to top,rgba(255,255,255,.94) 0%,rgba(255,255,255,.62) 16%,rgba(255,255,255,0) 34%);
}
.slide--v6 .plate__caption{--fg:var(--ink);--fg-dim:rgba(28,24,19,.72);--line:rgba(28,24,19,.3)}
.slide--v6 h1{font-size:clamp(36px,4.6vw,58px);line-height:1.05}
.slide--v6 .plate__caption p{font-size:16.5px}
/* The same two outlines, with ink where the others have white: white text
   inside an accent line would vanish on the sweep. */
/* The light slide's, and the event's: the label in ink, since white inside an
   accent line vanishes on a pale sweep and on white paper alike. */
.slide--v6 .button,
.eventback .button{color:var(--ink)}
.slide--v6 .button:hover,
.eventback .button:hover{background:rgba(28,24,19,.06);color:var(--ink);border-color:var(--ink)}
.slide--v6 .button--ghost{border-color:rgba(28,24,19,.45)}
@media (max-width:1080px){
  .plate__caption{grid-template-columns:1fr;gap:16px}
  .plate__actions{justify-content:flex-start}
}
@media (max-width:700px){
  .plate{aspect-ratio:3/4}
  .plate__top{height:120px}
}

/* ============================================================
   5 · Sections
   ============================================================ */
.section{padding-block:var(--rhythm);background:var(--bg);color:var(--fg)}
.section--flush{padding-top:0}
.split{display:grid;grid-template-columns:5fr 7fr;gap:clamp(28px,5vw,80px);align-items:start}
@media (max-width:860px){.split{grid-template-columns:1fr}}
/* The lede pair: the name of the section is centred over its own column, and the
   prose is justified so its right edge lands on the same line as the pictures
   below it — the wrap's right edge, which is why the measure is dropped here.
   Justification without hyphenation opens rivers, so the language is declared on
   the section and the hyphens are switched on with it. */
.split--lede .display{text-align:center}
.split--lede .body{max-width:none;text-align:justify;hyphens:auto}
/* The one action a story can carry, under its paragraphs. */
.split--lede .button{margin-top:clamp(20px,2.4vw,32px)}
/* Or the house's mark, where the story signs instead — Services since 21
   September 2026. Drawn as the brand page's maker signs: the mark in ink at
   the ink mark's opacity, centred under the last line at the same distance
   the brand page keeps between its last line and its mark — and half as
   large again as a maker's mark, at the project owner's word the same day:
   the house signs its own page larger than a maker signs his. */
.split--lede .logo--sign{
  height:clamp(51px,5.1vw,78px);width:auto;aspect-ratio:682/402;
  color:var(--ink);opacity:.82;margin:clamp(80px,7.2vw,112px) auto 0;
}
@media (max-width:860px){.split--lede .display{text-align:left}}

/* The card wall, as a rail. Ways into the site, each a picture with a name on
   it — hand-picked, never generated, and never more than a step from anywhere.

   How many cards there are is not fixed. The row shows --per of them and the
   arrows move it by one card, not by a screenful — a screenful throws away every
   card the eye had just started on, and there is then nothing to carry across
   the move. When every card is already in view the rail has nothing to move and
   its navigation takes itself away, so the section is honest with three cards
   and with thirty. */
/* The row takes the page and not the column, since 14 September 2026 — the
   page's own edge, where the masthead and the footer stop. It ran to the hero
   plate's hairline for an hour and was pulled back the same day: five tall
   pictures at the full width of the window read as a wall, where at the
   page's edge they read as a row on the page. The head and the foot of the
   section stand on the cards' own edges.

   Air above the kicker, because the lede above is on white and this is on
   paper: the seam between the two grounds needs a margin the kicker can stand
   off, where two paper sections could run flush. */
.section--range{padding-top:clamp(28px,3vw,48px)}
/* Where the row has a foot — the landing's range and the brand page's, not
   the About page's, which has a kicker and no rail — the cards stand as far
   from the section's foot as from its head, and the words and the arrows
   under them as far from the cards as the kicker above; asked for on 20
   September 2026, the landing in the morning and the brand page after it.
   The head row and the foot row are the same height (`--rangerow`, the
   kicker's line: 12.5px at the body's 1.72), each with the same margin
   against the cards, and the padding is the same at both ends; the page's
   rhythm, which every other section keeps, does not apply here. The arrows
   are 34px targets in a 22px row — they overhang it by six each way rather
   than making it taller. */
.section--range:has(.rangefoot){--rangerow:calc(12.5px * 1.72);padding-bottom:clamp(28px,3vw,48px)}
.section--range .rangehead{min-height:var(--rangerow)}
.section--range .rangefoot{height:var(--rangerow)}
.section--range .rangefoot .railarrow{margin-block:calc((var(--rangerow) - 34px) / 2)}
.wrap--range{max-width:none;padding-inline:var(--edge)}
/* A row that goes out to the hero plate's hairline rather than the page's
   edge: the landing's range, asked for on the evening of 14 September 2026
   once the head had become a ruled row — with a rule running the width of
   the page above them, five pictures at the same width read as the page's
   own band rather than as a wall — the About page's values since the 16th,
   and the brand page's range since the same evening. */
.wrap--range.wrap--bleed{padding-inline:var(--plate-edge)}
/* The row's measures are declared on the wrap rather than on the rail, so
   the head and the foot can read them too — see the rule under the rail. */
.wrap--range{--per:5;--gap:14px;--tile:.478}
.cardwall{--tile-max:560px;--card-pad:clamp(20px,2.1vw,36px);overflow:hidden}
/* Five across down to 1060, from 1200 until 16 September 2026: a 14-inch
   Windows laptop at its recommended scale is 1080 to 1280 CSS pixels wide,
   and the client's range is five on a first screen. Below 1060 the card
   would be under 195px wide and the line under it would take a fourth row. */
@media (max-width:1060px){.wrap--range{--per:4;--tile:.75}}
@media (max-width:1000px){.wrap--range{--per:3;--tile:.75}}
@media (max-width:760px){.wrap--range{--per:2;--tile:.75}}
@media (max-width:520px){.wrap--range{--per:1;--tile:1.33}}
.cardwall__track{
  /* A row with fewer cards than places is centred; a row with more keeps its
     start, because `safe` refuses to centre what would overflow both ways
     and hand the rail a first card it cannot reach. */
  display:flex;gap:var(--gap);justify-content:safe center;
  transform:translate3d(calc(var(--x,0) * -1px),0,0);
  transition:transform .8s cubic-bezier(.22,.35,.03,1);
}
.cardwall__track>.card{
  flex:0 0 calc((100% - (var(--per) - 1) * var(--gap)) / var(--per));
}
/* A row with fewer cards than places is centred, and its head and its foot
   stand on the cards' edges rather than the page's — the About page's three
   values under a kicker and a rule that ran the width of the page, asked
   for on 21 September 2026, and the same for any brand whose range is
   short. The wrap carries how many cards there are (`--cards`), and the
   width of that many at the row's own card width, with the gaps between
   them, is the head's and the foot's: the page's width, and no wider, once
   the cards fill the row. */
.rangehead,.rangefoot{
  width:min(100%,calc(100% * var(--cards,var(--per)) / var(--per) - var(--gap) * (var(--per) - var(--cards,var(--per))) / var(--per)));
  margin-inline:auto;
}
/* The card is a container so that what is written on it can be sized by the
   card's own width rather than the window's: five across, a card is 285px
   wide on a 14-inch Mac and 239px on a 14-inch Windows laptop at its
   recommended scale, and the row is drawn for both. */
.card{position:relative;overflow:hidden;display:block;isolation:isolate;container-type:inline-size}
/* Five across, and as tall as the page allows — the client asked for the range
   to be one screen of tall pictures, and the drawing sets the card at about
   0.48, nearly twice as tall as wide.

   Two numbers govern the height, and the smaller wins. The ratio makes the card
   grow with the window — on a 14-inch laptop at 1280 wide that is a 450px card,
   at 1673 wide 570 — and the ceiling stops it there: on a wide monitor the
   five would otherwise go on growing and the section would no longer be a
   screen. Past the ceiling the card keeps its height and widens, back towards
   3:4 on the widest monitors, which is the shape the photographs were made in.

   The ceiling is set by the agreed reference screen, which since 16 September
   2026 is a 14-inch MacBook Pro: 1512 CSS pixels wide, and with the menu bar,
   the browser's own panels and the Dock about 800 tall. (A day was spent
   reckoning in 1920 pixels first. A 14-inch panel is never 1920 CSS pixels
   wide: macOS draws it at 1512 and Windows recommends 150%, which is 1280,
   because at 100% everything on it is 1.7 times smaller than it was designed
   to be.) What has to fit in the 800 is not the card but the screen: the
   fixed bar (75), the section's own top padding, the head row and the foot
   row (122 together), and the card, with the arrows still showing at the
   foot. 800 less 197 is 603; the ceiling is 560, with the difference to
   spare, and on that screen the card is 285 wide, so it is drawn at 0.51
   rather than the drawing's 0.48. On anything larger the card stops at 560
   and widens; on a 14-inch Windows laptop at its recommended 150% the row
   does not fit on one screen, and that is a known cost of the reference
   chosen. The number is one to raise only with the reference screen.

   The ceiling is also what the photographs can bear. Every card picture in the
   library is 700 by 930, and cut to this ratio 446 by 930 remain: sharp to 930
   of card height on an ordinary screen, and to 465 on a retina one, where the
   560px card is drawn at one and a fifth times its material. Taller cards on the
   largest screens — the second version considered on 14 September 2026 — wait
   for originals of about 2000px; the ceiling is one number to raise when they
   arrive.

   Narrower than five across the cards go back to 3:4, because a slender card
   only reads as slender while there are five of them. */
.card img{
  width:100%;aspect-ratio:var(--tile,.75);max-height:var(--tile-max,none);object-fit:cover;
  object-position:var(--focus,center);
  transition:transform 1.5s cubic-bezier(.22,.35,.03,1);
}
.card:hover img,.card:focus-visible img{transform:scale(1.04)}
.card__veil{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,.82) 0%,rgba(0,0,0,.34) 34%,rgba(0,0,0,0) 66%);
}
/* Less at the floor than at the sides: the label sits close to the card's
   bottom edge, the way a caption sits on a photograph. */
.card__label{
  position:absolute;inset:auto 0 0 0;color:#fff;
  padding:var(--card-pad,clamp(18px,1.6vw,26px));padding-bottom:clamp(9px,1.3vw - 5px,17px);
}
.card__label h3{
  font-family:var(--display);font-weight:300;letter-spacing:-.01em;
  font-size:clamp(26px,2.1vw,36px);line-height:1.05;transition:color .25s;
}
.card:hover .card__label h3,.card:focus-visible .card__label h3{color:var(--brass-lift)}
/* The short rule under the name, as the drawing has it: a mark that the name
   is a title and the line under it is a sentence about it. */
.card__label h3::after{
  content:"";display:block;width:52px;height:1px;margin-top:14px;
  background:rgba(255,255,255,.5);
}
/* As many lines of room as the longest line in view takes. The label is
   anchored to the card's floor, so the name and its rule would otherwise
   stand higher on a card whose line wraps twice than on one whose line fits
   once — five names at three different heights across one row. The room is
   reserved instead and the line sits at the top of it, so the name and the
   rule are at one height on every card.

   How much room is the script's answer, `--lines` on the wall: it counts the
   lines of every card in view and reserves the most, so a row of one-line
   phrases keeps its names low and a row with a three-line sentence in it
   lifts them all together — asked for on 20 September 2026, after a fixed
   three held every name a line high on a brand whose lines were short, and
   a fixed two let Esprit's five names stand at three heights. Without the
   script it is three, the most any line takes at any width the row is drawn
   at. */
.card__line{
  margin-top:16px;font-size:13.5px;line-height:1.45;min-height:calc(var(--lines,3) * 1.45em);
  color:rgba(255,255,255,.8);max-width:26ch;
}
/* At rest the card carries its name and its line. What the pointer brings out
   is the word that says it goes somewhere — not hidden by opacity but a row of
   no height, so the line sits at the bottom edge until the word opens and
   lifts it. Nothing else on the card moves. */
.card__more{
  display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .5s cubic-bezier(.22,.35,.03,1);
}
.card:hover .card__more,.card:focus-visible .card__more{grid-template-rows:1fr}
/* The row's own padding travels with the word: the line has to be as far from
   the bottom edge at rest as the word is once it is out. */
/* One line, on both 14-inch screens. "Explore → Coming soon" is 210px at the
   label size, and a card's inner width is 221px on the Mac but 185px on the
   Windows laptop — where "Coming soon" broke in two after "coming", 20
   September 2026. So the size follows the card: 12px on the Mac, 10px on
   Windows, the tracking with it as it is in em. Neither word may break
   inside itself; below 1250 or so, where even 10px is too long for the card,
   the whole of "Coming soon" moves to a second line instead. */
.card__go{
  overflow:hidden;display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;padding-top:22px;
  font-family:var(--ui);font-size:clamp(10px,4.2cqi,var(--label-size));font-weight:var(--label-weight);
  letter-spacing:var(--label-track);text-transform:uppercase;color:#fff;white-space:nowrap;
  opacity:0;transition:opacity .4s ease;
}
.card__go svg{width:16px;height:16px;flex:none}
.card:hover .card__go,.card:focus-visible .card__go{opacity:1;transition-delay:.1s}
/* Where there is no pointer the word is always out — a card that only says
   where it goes under a hover says nothing on a phone. */
@media (hover:none){
  .card__more{grid-template-rows:1fr}
  .card__go{opacity:1}
}
/* A card with no photograph is still a card: same box, same name in the same
   place, and its ground is the page's own night rather than a grey stand-in.
   The height comes from the ratio directly, because there is no picture to take
   it from — everything else in the row is a 3:4 image, and this has to be the
   same height or the rail goes ragged. */
.card--bare{
  aspect-ratio:var(--tile,.75);max-height:var(--tile-max,none);background:var(--night);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);
}
.card__wanting{
  position:absolute;top:var(--card-pad,clamp(18px,1.6vw,26px));left:var(--card-pad,clamp(18px,1.6vw,26px));
  font-family:var(--ui);font-size:10.5px;font-weight:500;letter-spacing:.2em;
  text-transform:uppercase;color:rgba(255,255,255,.42);
}

@media (prefers-reduced-motion:reduce){
  .card img,.card__more,.card__go,.cardwall__track{transition:none}
}

/* The head and the foot of the section, as the drawing sets them: the kicker
   with a line in the serif opposite; under the row, the navigation on the
   centre line and a second line at the right with a rule leading out of it.
   The drawing led a rule into the kicker as well; it came off on request the
   same day. Both rows stand on the photographs' own edges, not on the words
   inside them — asked for on the same day, after an hour on the inner line. */
/* Grey, not the ink dimmed: the phrases at the ends of the rules are a
   decoration in the drawing's sense and stand a step further back than the
   prose. The same grey on the range's head and foot lines. */
:root{--phrase:#8E8A84}
/* Since the evening of 14 September 2026 the head is a rule with a phrase at
   each end — the kicker at the left, a second phrase in the same small
   capitals at the right, and the rule taking whatever is between them — the
   way the drawing of 14 September sets such rows. */
.rangehead{
  display:flex;align-items:center;gap:clamp(18px,2.4vw,36px);
  margin-bottom:clamp(10px,1.1vw,16px);
}
.rangehead__rule{flex:1;height:1px;background:var(--line)}
.rangehead .kicker{margin-bottom:0}
.rangehead__line{
  font-family:var(--ui);font-size:11px;font-weight:500;letter-spacing:.24em;
  text-transform:uppercase;color:var(--phrase);text-align:right;
}
.rangefoot{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:24px;
  margin-top:clamp(10px,1.1vw,16px);
}
.rangefoot .railnav{grid-column:2;margin-top:0}
.rangefoot__line{
  grid-column:3;justify-self:end;display:flex;align-items:center;gap:22px;
  font-family:var(--ui);font-size:10.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--phrase);
}
.rangefoot__line::after{content:"";width:48px;height:1px;background:currentColor}
@media (max-width:860px){
  .rangehead__line,.rangefoot__line{display:none}
  .rangefoot{display:block}
}

/* The rail's own navigation, and deliberately not the slider's. The slider sits
   on a photograph, so its controls carry mats to be legible at all; this sits on
   paper, so a mat would be a box drawn for no reason. The marks are the same —
   a dot for each position and a dash for the one showing — because they mean the
   same thing in both places. */
.railnav{
  display:flex;align-items:center;justify-content:center;
  gap:clamp(16px,2vw,28px);margin-top:clamp(18px,1.8vw,28px);
}
.railnav[hidden]{display:none}
.railarrow{
  width:34px;height:34px;display:grid;place-items:center;
  border:0;background:none;padding:0;color:var(--fg);cursor:pointer;
  transition:color .2s,opacity .25s;
}
.railarrow:hover{color:var(--brass)}
.railarrow[disabled]{opacity:.22;cursor:default;color:var(--fg)}
.railarrow svg{width:22px;height:22px;display:block}
/* On a touch screen the row is swiped, so the arrows are a control nobody
   reaches for and two more things standing beside the dots. The dots stay:
   they say how far along the row you are, which a swipe does not. Asked of the
   device rather than of the width — a phone held sideways is still a phone, and
   a narrow window on a laptop still has a pointer in it. */
@media (hover:none) and (pointer:coarse){
  .railarrow{display:none}
}
/* A card is drawn in two states, at rest and under a pointer, and on a screen
   with no pointer only one of them can ever be reached. So they collapse into
   the one the card can actually be in: the line under the name is shown at rest
   rather than waiting for a hover that never comes.

   Without this the card answers a tap by entering its hover state and staying
   there: the text opens after the finger has gone, on a card the reader has
   already scrolled past. */
@media (hover:none){
  .card__more{grid-template-rows:1fr}
  .card__more>p{opacity:1}
  .card:hover img{transform:none}
  /* The name stays white on every card. Its accent belongs to a pointer resting
     on the card and leaving again; a tap has no second half, so the colour it
     turns is a colour it keeps, on a card the reader has already gone past. */
  .card:hover .card__label h3{color:#fff}
}
/* The row is scrolled rather than moved. A finger dragging a row of cards is
   something every browser already does, with its own momentum, its own rubber
   band at the ends and its own idea of when a gesture belongs to the page
   instead — none of which a script can reproduce and all of which it can fight.
   So the transform comes off and the rail becomes what it looks like: a strip
   that scrolls, snapping to whichever card it is let go over. The script stops
   driving it and only reports where it got to, which is what the dots say.

   Two conditions and not one. A coarse pointer is the reason for it; a narrow
   window is where it is right anyway, and it is also the answer that does not
   depend on a device reporting its own input honestly. Where both the arrows
   and this are in force they agree: an arrow scrolls the rail instead of
   moving it, which is one line in the script. */
@media (max-width:760px), (hover:none) and (pointer:coarse){
  .cardwall{
    overflow-x:auto;overflow-y:hidden;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    /* The bar is noise under a row of pictures, and the dots already say the
       one thing it would. */
    scrollbar-width:none;
  }
  .cardwall::-webkit-scrollbar{display:none}
  /* And nothing may declare the sideways gesture off-limits. `pan-y` on the row
     was right while a script owned the drag — it is exactly how you tell the
     browser to keep its hands off a horizontal one — and it is the one thing
     that stops a scrolling rail from scrolling. */
  .cardwall,.cardwall__track,.cardwall__track>.card{touch-action:auto}
  .cardwall__track{transform:none;transition:none}
  .cardwall__track>.card{scroll-snap-align:start}
}
/* The rail's marks read the section's own ink rather than the paper token. It
   is the same row on a light section and on a dark one, and --ink means "text on
   paper" — the moment a rail sits on the night, a component that names it goes
   invisible. --fg is what the section says its ink is, whichever ground it has,
   so the row needs no variant and the class needs no name for a colour. */
.railnav .dot{background:var(--fg);opacity:.3}
.railnav .dot:hover{background:var(--fg);opacity:.55}
/* The dash carries a shade more weight here than on the photograph. White on a
   darkened picture reads heavier than it is drawn; ink on paper reads exactly as
   thick as it is, so the same 4px would come out the thinner of the two.

   6px and not 5px, because the row centres the marks against a 6px dot: an odd
   height leaves half a pixel above and half below, and the browser puts that
   half somewhere — which is what made the dash sit low next to its neighbours.
   Matching the dot's box removes the fraction rather than nudging it back. */
.railnav .dot[data-active]{background:var(--fg);opacity:1;height:6px;border-radius:3px}

/* ============================================================
   К17 · Feature band — a full-bleed picture with a panel over it,
   one heading, one paragraph, one link.

   It has a number of its own because it is neither of the two it
   would otherwise be filed under: К3 puts the picture beside the
   text and its link always points at a section; К6 is prose and
   carries no buttons. This is the construction the client's named
   reference uses between its sections, and the difference that
   matters is the panel — К2 needs the photograph to be dark enough
   to carry white text, and this one brings its own ground, so a
   bright picture is as usable as a dark one.
   ============================================================ */
.band{position:relative;isolation:isolate;overflow:hidden;background:var(--night)}
.band img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:var(--focus,center);z-index:-1;
}
.band__inner{
  /* Wider than the page's own gutter: the panel and its pale plane are pushed
     in off the edge, so the picture keeps a margin of its own on both sides. */
  max-width:none;padding:clamp(48px,7vw,104px) clamp(20px,9vw,200px);
  min-height:clamp(360px,38vw,560px);display:flex;align-items:center;
  /* A stacking context of its own, so the pale square below can sit behind the
     panel without falling behind the photograph as well. */
  isolation:isolate;
}
.band--right .band__inner{justify-content:flex-end}
/* A band whose photograph stays where it is while the page moves over it: the
   picture is fixed to the viewport, and the band is a window cut in the page
   through which it is seen. clip-path is what cuts the window — overflow does
   not clip a fixed descendant, whose containing block is the viewport, and
   clip-path does without becoming a containing block itself. The panel
   travels with the page as before; only the photograph holds still. Every
   brand page's band, since 17 September 2026; the landing's bands are not. */
.band--fixed{clip-path:inset(0)}
.band--fixed img{position:fixed;height:100vh;height:100dvh}
/* Not on a phone. A landscape photograph held to a portrait screen's full
   height is cropped to the middle third of its width, and the subject the
   band was chosen for goes with the rest; at this width the band is the
   ordinary one, the photograph covering the band's own box, as the landing's
   bands are. It was a picture problem before it was seen to be a rendering
   one, 17 September 2026. */
@media (max-width:700px){
  .band--fixed{clip-path:none}
  .band--fixed img{position:absolute;height:100%}
}
/* A band that opens a page, under the head: held to one screen on the
   reference laptop together with the fixed bar, which the landing's bands,
   met on the way down, are not. The floor and the ceiling come in — the
   panel's words are what set the height, and the band's own air above and
   below them was what put it over. Measured on 16 September 2026: 716 to
   about 630 at 1512 wide, 611 to about 540 at 1269, against 725 and 575. */
.band--first .band__inner{padding-block:clamp(28px,4vw,60px);min-height:0}
/* The Services page's four bands are four frames rather than one run of
   picture, at the project owner's word of 23 September 2026. A black line
   between them says where one ends, and it is the height of the header when
   the header has collapsed to its bar — `--bar-h`, which is 75px on a desktop
   and 113 on a phone, where the bar carries the action above it. The page's
   own ground is what the line is made of: the gap is a margin, and `main`
   under it is night, so nothing is drawn that a section could not cover.

   Only this page. The brand pages and About run one band into the next on
   purpose — there the picture holds still while the page moves over it, and
   a seam would break exactly what that construction is for. */
.services{background:var(--night)}
.services .band + .band{margin-top:var(--bar-h)}
.band__panel{
  /* Role tokens, the same move a dark section makes: the panel is a ground of
     its own, and everything inside it reads the tokens rather than colours. */
  --fg:#FFFFFF;
  --fg-dim:rgba(255,255,255,.76);
  --accent:var(--brass-lift);
  color:var(--fg);max-width:470px;
  padding:clamp(26px,2.6vw,40px);
  background:linear-gradient(180deg,rgba(0,0,0,.42) 0%,rgba(0,0,0,.62) 100%);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
}
/* A second, paler plane behind the panel, pushed up and out past its corner —
   the construction the reference uses, and the thing that stops the panel
   reading as a box dropped on the photograph.

   It is genuinely behind: only the edge that sticks out is drawn. The panel is
   translucent, so a full rectangle would show through it and read as a second
   layer of tint rather than as something underneath. The clip keeps the strip
   along the top and the strip down the side — an L — and throws away the part
   the panel covers. Each band pushes it outwards, away from the middle of the
   picture — so the two go opposite ways: the left-hand panel throws its plane
   left, the right-hand one throws it right. */
/* The pair is centred, not the panel: the plane sticks out above, so the two
   together sit higher than the panel alone. A flex item is centred by its
   margin box, so a top margin of one whole offset moves the panel down by
   half of one — which is exactly what puts the composition on the middle. */
.band__panel{--plane:clamp(18px,2.4vw,38px);margin-top:var(--plane)}

/* The plane arrives. Two numbers describe where it is on the way: --travel is
   how far it still has to go, and --open is how much of it is still a plain
   square rather than the L it settles into. Both are zero at rest, which is the
   composition above — so the end state is the state the stylesheet describes,
   and the motion is a departure from it that JavaScript writes and then undoes.
   Nothing here depends on the script running: with no JavaScript, no scroll and
   no motion, the band is already in its finished position.

   The L is not a second shape faded in. It is the same polygon with one length
   in it: at --open 1 that length reaches the far side of the box and the notch
   closes up into a whole rectangle — the plane with its side still on it — and
   at 0 it is the plane's own offset, so the notch is exactly the corner the
   panel covers. One variable, one shape. */
.band__panel{--open:0;--cut:calc(var(--plane) + (100% - var(--plane)) * var(--open))}
.band__panel::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  background:rgba(255,255,255,.2);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  transform:translate3d(var(--travel,0px),0,0);
  /* up and to the left, with the top strip and the left strip left showing */
  inset:calc(var(--plane) * -1) var(--plane) var(--plane) calc(var(--plane) * -1);
  clip-path:polygon(0 0,100% 0,100% var(--cut),
    var(--cut) var(--cut),var(--cut) 100%,0 100%);
}
/* the band whose panel sits on the right throws its plane the other way */
.band--right .band__panel::before{
  inset:calc(var(--plane) * -1) calc(var(--plane) * -1) var(--plane) var(--plane);
  clip-path:polygon(0 0,100% 0,100% 100%,
    calc(100% - var(--cut)) 100%,calc(100% - var(--cut)) var(--cut),0 var(--cut));
}
.band__panel .kicker{color:var(--accent)}
.band__panel p{color:var(--fg-dim);margin-top:14px;font-size:15px}
/* A band that is read: the paragraph at the body's size, in the panel's
   own measure — Services' Custom Design & Installation, 21 September 2026. */
.band--read .band__panel p{font-size:var(--step0);line-height:1.6}
/* The kicker is a paragraph too, and the panel's paragraph rule was sizing
   it: 15px, and the reading size on a band that is read. It takes the
   kicker's own size back — the story's *Our services* — asked for on
   21 September 2026 when *Your system* went over the first band. */
.band__panel p.kicker{font-size:12.5px;margin-top:0;line-height:1.72}
.band__panel .button{margin-top:26px}
/* The pointer has to be answered on a band, and the button's own hover cannot
   do it here: it is brass going a shade lighter, which reads on paper and
   disappears on a translucent panel over a photograph. The slide's buttons have
   the same problem and the stylesheet already solves it there, for the same
   reason — so this is that solution for a solid button rather than a new idea.

   The chip turns: the paper ground and the night's ink, which is the palette's
   own inversion and is unmistakable over any picture. Asked for on
   23 September 2026, the hover having been reported as missing. */
.band__panel .button:hover{background:var(--paper);border-color:var(--paper);color:var(--night)}
@media (max-width:700px){.band__panel{max-width:none}}

.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
/* Square while a square fits, and a shorter box when the screen is short. Six
   squares three across are two rows of a third of the measure — about 810px of
   picture before the heading and the section's own air are counted, which is
   more than a laptop has. A gallery that has to be scrolled to be read as a
   gallery is not one.

   So the height is capped against the window rather than the width: two rows,
   the gap between them and the block's chrome — the section's rhythm top and
   bottom, and the kicker — have to sit inside one screen. `min` is doing the
   choosing, not a breakpoint: on a tall screen the square is the smaller number
   and nothing changes, on a short one the window is, and the pictures crop.
   They crop rather than shrink because object-fit is already cover — the frame
   changes shape, the photograph does not.

   svh and not vh: on a phone vh is the tallest the window ever gets, which is
   the one height the picture is never actually seen at. */
.gallery img{
  aspect-ratio:1;object-fit:cover;width:100%;display:block;
  max-height:max(180px,calc((100svh - var(--rhythm) * 2 - 62px) / 2));
}
/* The one that is open is not two rows of anything — it fills the block. */
.gal.is-open img{max-height:none}
.gal{position:relative;display:block;cursor:zoom-in}
/* Opening a picture does not move the others: it is laid over the whole grid,
   so nothing reflows and the space it fills is exactly the space the six of
   them occupied. Closing puts it back by removing one class. */
.gallery{position:relative}
.gal.is-open{
  position:absolute;inset:0;z-index:2;cursor:default;
  animation:gal-open .5s cubic-bezier(.22,.35,.03,1);
}
.gal.is-open img{width:100%;height:100%;aspect-ratio:auto}
/* An open picture hides its corner mark and shows a cross instead — the mark
   says "this one opens", the cross says "this one closes", and they are the
   same 4px weight so the swap reads as one control changing state. */
.gal.is-open::before{display:none}
.gal-close{
  position:absolute;top:18px;right:18px;z-index:3;display:none;
  width:38px;height:38px;padding:0;border:0;background:none;cursor:pointer;
  color:#fff;filter:drop-shadow(0 0 5px rgba(0,0,0,.55));
}
.gal.is-open .gal-close{display:block}
.gal-close svg{width:100%;height:100%;display:block}
@keyframes gal-open{from{opacity:0;transform:scale(.985)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.gal.is-open{animation:none}}
/* A corner mark on the four pictures that sit at the corners of the grid, each
   turned to face its own corner. The two middle pictures carry none.

   Not two borders: a border's free end is cut square, and these are cut at 45°.
   So it is one filled shape with a clip path — six points, an L with a mitred
   corner and both ends bevelled — and the other three corners are the same
   shape flipped, which keeps one definition rather than four. */
.gal--tl::before,.gal--tr::before,.gal--bl::before,.gal--br::before{
  content:"";position:absolute;pointer-events:none;
  width:clamp(34px,4.4vw,58px);height:clamp(34px,4.4vw,58px);
  background:#fff;
  /* 4px — the same weight as the dash that marks the slide showing. */
  clip-path:polygon(0 0,100% 0,calc(100% - 4px) 4px,4px 4px,4px calc(100% - 4px),0 100%);
  /* Half of these pictures are bright where their corner falls, and white on a
     sunlit floor disappears. The shadow keeps one mark the same mark on all four. */
  filter:drop-shadow(0 0 5px rgba(0,0,0,.5));
}
.gal--tl::before{inset:16px auto auto 16px}
.gal--tr::before{inset:16px 16px auto auto;transform:scaleX(-1)}
.gal--bl::before{inset:auto auto 16px 16px;transform:scaleY(-1)}
.gal--br::before{inset:auto 16px 16px auto;transform:scale(-1,-1)}
@media (max-width:700px){.gallery{grid-template-columns:1fr 1fr}}

.docs{border-top:1px solid var(--line);max-width:760px}
.docs li{
  display:flex;justify-content:space-between;gap:20px;align-items:baseline;
  padding-block:16px;border-bottom:1px solid var(--line);
}
.docs a{transition:color .2s}
.docs a:hover{color:var(--accent)}
.docs .meta{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;color:var(--fg-dim);white-space:nowrap}

/* ============================================================
   6 · Form — WooCommerce's own markup and class names, so the
   enquiry form and the phase-2 checkout are one stylesheet.
   ============================================================ */
.woocommerce-notices-wrapper{display:grid;gap:10px;margin-bottom:26px;max-width:640px}
.woocommerce-message,.woocommerce-error,.woocommerce-info{
  border-left:2px solid var(--accent);padding:12px 16px;font-size:14px;
  background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--fg);
}
.woocommerce-error{border-left-color:var(--danger);background:color-mix(in srgb,var(--danger) 8%,transparent)}
.woocommerce-info{border-left-color:var(--fg-dim);background:color-mix(in srgb,var(--fg) 6%,transparent)}

/* align-content, or the taller column stretches its neighbour's rows: the pair
   Telephone / Which model differ by a description line, and without this the
   select is pushed half that line lower than the field beside it. */
.form-row{display:grid;gap:6px;margin-bottom:18px;align-content:start}
.form-row-first,.form-row-last{margin-bottom:0}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px}
@media (max-width:640px){.form-grid{grid-template-columns:1fr}}
.form-row label{
  font-family:var(--ui);font-size:10.5px;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--fg-dim);
}
.form-row label .required{color:var(--accent);text-decoration:none}
.form-row label .optional{opacity:.62;letter-spacing:.04em;text-transform:none}
.woocommerce-input-wrapper{display:grid;gap:6px}
.input-text,select,textarea{
  width:100%;border:1px solid var(--line);border-radius:0;background:transparent;
  padding:13px 14px;font-family:var(--ui);font-size:15px;color:var(--fg);
  transition:border-color .18s,box-shadow .18s;
}
/* A select is the one control the browser draws its own way. Three things have
   to be said or it does not match the fields beside it:
   - line-height, or it inherits the page's 1.72 and stands 12px taller than an
     input with the same padding;
   - room on the right for the arrow, or a long model name runs under it;
   - the arrow's own colour, so it stays solid when the text greys out below. */
select{
  appearance:none;-webkit-appearance:none;
  /* Chrome lays a select's own text out its own way, and line-height does not
     reach it — so the height is stated outright and matched to the input:
     13 + 13 padding, 1 + 1 border, 20 of text. */
  height:48px;padding-block:0;padding-right:40px;
  background-image:linear-gradient(45deg,transparent 50%,var(--fg) 50%),
  linear-gradient(135deg,var(--fg) 50%,transparent 50%);
  background-position:calc(100% - 19px) 50%,calc(100% - 14px) 50%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
/* Nothing chosen yet is a placeholder, not an answer, and it reads as one —
   the same grey as the empty fields around it. */
select:has(option[value=""]:checked){color:color-mix(in srgb,var(--fg-dim) 50%,transparent)}
textarea{min-height:120px;resize:vertical;line-height:1.6}
.input-text::placeholder,textarea::placeholder{color:var(--fg-dim);opacity:.5}
.input-text:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent);
}
.woocommerce-invalid .input-text,.woocommerce-invalid textarea{border-color:var(--danger)}
.woocommerce-invalid .description{color:var(--danger)}
.description{font-size:12.5px;color:var(--fg-dim);opacity:.85;line-height:1.5}
/* The radio pair reads as one answer with two halves rather than as two rows of
   a list: side by side while there is room, stacked when there is not, and the
   labels set like the checkbox's — sentence case, dim, at reading weight —
   because they are what is being chosen between, not what the field is called. */
/* The field that is not there.

   The trap is off the page rather than `display:none`: a robot that reads the
   stylesheet skips what is hidden and fills what is merely elsewhere. It is
   out of the tab order in the markup and out of the accessibility tree, so no
   person meets it either way.

   The answer to a send has no rule of its own: it is a `.woocommerce-message`
   in the notices wrapper, which is where the form's other two answers are
   drawn too. */
.enquiry-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.radio-set{display:flex;flex-wrap:wrap;gap:10px 30px;padding-top:6px}
.radio-row{display:flex;gap:10px;align-items:center}
.radio-row input{width:15px;height:15px;margin:0;accent-color:var(--accent);flex:0 0 auto}
.radio-row label{
  font-size:13.5px;letter-spacing:0;text-transform:none;color:var(--fg-dim);
  font-weight:400;margin:0;cursor:pointer;
}
.form-row.checkbox{display:flex;gap:10px;align-items:flex-start;margin-bottom:24px}
.form-row.checkbox input{
  width:15px;height:15px;margin:4px 0 0;accent-color:var(--accent);flex:0 0 auto;
}
.form-row.checkbox label{
  font-size:13.5px;letter-spacing:0;text-transform:none;color:var(--fg-dim);font-weight:400;
}
.form-actions{display:flex;gap:11px;flex-wrap:wrap;align-items:center}

.button{
  font-family:var(--ui);font-size:10.5px;font-weight:500;letter-spacing:.2em;
  /* The label is centred in the box rather than resting on the top padding, and
     the line height is stated rather than inherited. A row of buttons is a mix
     of <a> and <button>: the link inherits the page's 1.72, the button keeps the
     browser's own `normal`, and the two then stand six pixels apart in a row
     that centres them instead of stretching them. */
  display:inline-flex;align-items:center;justify-content:center;line-height:1.2;
  text-transform:uppercase;padding:15px 26px;white-space:nowrap;cursor:pointer;
  border:1px solid var(--accent);background:var(--accent);color:var(--accent-fg);
  transition:background .2s,color .2s,border-color .2s,opacity .2s;
}
.button:hover{background:var(--brass-lift);border-color:var(--brass-lift)}
.button--ghost{background:transparent;color:var(--accent)}
.button--ghost:hover{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}
.section--dark .button--ghost{color:#fff;border-color:rgba(255,255,255,.55)}
.section--dark .button--ghost:hover{background:rgba(255,255,255,.1)}
.button[disabled]{opacity:.36;cursor:default}
.button[disabled]:hover{background:var(--accent);border-color:var(--accent)}

/* ============================================================
   7 · Brand strip and footer
   ============================================================ */
/* Three rows, stated, and every one of them centred. Left to itself the strip
   wrapped where it ran out of room, which put eight and eight on a wide screen
   and a stub of two on a narrow one; a column grid fixed the count but hung the
   short last row against the left edge, because a grid has columns and a partial
   row cannot be centred in them.

   So the count is forced in the row and not in the columns: two items of no
   width and no height, each taking a whole line, break the flex row after the
   fifth mark and after the eleventh. Every line is then its own centred row of
   5, 6 and 5, and the breaks cost nothing — they are not marks, they carry no
   ink and no space.

   Where six no longer fit across, the breaks take themselves out and the strip
   wraps as it did. A forced row is only worth forcing while it is a row. */
.marks{display:flex;flex-wrap:wrap;gap:26px 46px;align-items:center;justify-content:center}
.marks__break{flex:0 0 100%;height:0;margin:0;padding:0}
@media (max-width:1100px){.marks__break{display:none}}
@media (max-width:760px){.marks{gap:22px 32px}}
/* Inside the footer the strip is a band between two rules rather than a row
   under a heading, and it takes the footer's air: rows further apart, marks
   further apart, so sixteen of them read as a band and not as a crowd. The
   gap scales with the window and settles where the drawing has it on a
   laptop; below 760 the general rule above takes over and packs them again,
   until the lanes replace the wrapped strip altogether.

   The row gap is written at half of what is wanted. A forced break is a flex
   item on a line of its own, and the row gap is paid on both sides of it —
   so while the breaks are in, every row stands two gaps from the next. Below
   1100 the breaks take themselves out and the gap is paid once, and the
   number doubles to keep the distance. */
.foot-marks{
  padding-block:clamp(40px,5.2vw,76px) clamp(40px,5.2vw,72px);
  border-bottom:var(--line-w) solid var(--line);
}
.foot-marks .marks{gap:clamp(18px,2.4vw,36px) clamp(28px,3.4vw,92px);padding-inline:5.5vw}
/* Three rows on a 14-inch screen, and the rows inset from the rules by a
   twentieth of the window on each side, as the drawing of 16 September 2026
   has them — the marks stand inside the rules, not on them. On a Mac that is
   1512 CSS pixels wide and the three rows hold at full size; on Windows at
   its recommended 150% it is 1280, and there the first row — six marks with
   Franco Serblin among them — did not fit, so the seventh mark stood alone on
   a row of its own. Below 1400 the marks come down by a step at each width,
   every one by the same factor so the balance measured between them holds;
   the height rule above multiplies by it. Measured on 16 September 2026:
   6, 5 and 5 from 1150 to 1903 wide; by 20 September the sixth no longer fit
   the first row on a 14-inch screen, and `strip_breaks()` now composes 5, 6
   and 5 — the wide marks in the first row, the sixth among the narrow ones. */
@media (max-width:1400px){.foot-marks{--mark-scale:.95}}
@media (max-width:1300px){.foot-marks{--mark-scale:.9}}
@media (max-width:1250px){.foot-marks{--mark-scale:.85}}
@media (max-width:1100px){.foot-marks .marks{row-gap:clamp(36px,4.8vw,72px)}}
@media (max-width:760px){.foot-marks .marks{gap:22px 32px}}
@media (max-width:700px){.foot-marks{padding-block:36px}}
/* One of the sixteen is still a word — Bugatti Audio by Tidal, a co-branded line
   whose lockup is licensed and has to come from TIDAL rather than be lifted. It
   is set to read as the same weight as the pictures beside it rather than as a
   gap in the row. */
.marks li{
  font-family:var(--ui);font-size:13px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--fg-dim);transition:color .2s;
}
.marks li:hover{color:var(--fg)}
/* Set as a wordmark, not as a name: capitals at WADAX's height (21px) and at
   its stroke — the WADAX mark is a light geometric, so the face's light weight,
   spaced as widely — at the marks' own opacity. Jost's capitals are seven
   tenths of the em, so 30px of type is 21px of letter; the project owner
   asked for three pixels less on the page, so 26px of type, 18px of letter. */
.marks__word{
  display:block;font-size:26px;line-height:1;font-weight:300;letter-spacing:.2em;
  color:#fff;opacity:.72;transition:opacity .2s;
}
.marks li:hover .marks__word{opacity:1}

/* ---- The strip as two running lanes, below 700 ----------------------------
   Sixteen marks wrapped into a phone's width is five or six rows of a column
   each — a wall of logotypes where the desktop has a band. Running them takes
   the height back and, more usefully, gives every mark the same size on screen
   as it has on a laptop instead of shrinking the row to fit.

   Two lanes, opposite ways. One lane moving alone reads as a slideshow that
   will not stop; two moving against each other read as a texture, which is what
   the strip is for — the eye takes in that there are many, then picks out the
   ones it knows. A storefront with only a few brands gets one lane, because two
   lanes of three is not a texture, it is two short queues.

   Speed is set in pixels per second by the script, not in seconds per loop, so
   `.ae` with sixteen and `.ru` with six run at the same pace rather than the
   same duration.

   The lanes are built by script from the list that is already on the page, and
   the list stays in the document as the source. With no JavaScript, or with
   reduced motion asked for, nothing is built and the wrapped strip is what
   remains — which is a complete answer rather than a degraded one.

   Every item carries its own trailing margin instead of the row carrying a gap,
   which is what makes the loop seamless: two copies then tile exactly, and the
   halfway point the animation returns to is the start of the second copy to the
   pixel. With a flex gap it is half a gap out, and the strip stutters once a
   minute in a way nobody can name. */
/* `.marks` is display:flex, and a class beats the browser's own rule for the
   hidden attribute — without this the list the lanes were built from stays on
   the page underneath them. */
.marks[hidden]{display:none}
/* The motion itself is not here. A lane can be flicked to run faster or thrown
   the other way for a moment, and a CSS animation's rate cannot be changed
   without it jumping — so the loop is held by the Web Animations API, where
   playbackRate is a number that can be turned. What is here is everything that
   does not move.

   pan-y for the same reason the hero has it: the strip sits near the foot of
   the page, where a gesture is far more often the page being scrolled than a
   lane being pushed. */
.marquee{display:grid;gap:22px;touch-action:pan-y}
.marquee__lane{overflow:hidden}
.marquee__track{display:flex;align-items:center;width:max-content;will-change:transform}
.marquee__track li{margin-inline-end:34px}
/* A mark is a link and nothing else: not text to select and not a picture
   to drag. On a Mac the pointer over the strip turned to the text cursor at
   times and the mark under it would not press, 20 September 2026 — a
   selection had begun on the strip and was swallowing the click. Nothing
   here is there to be selected, so nothing is selectable, and the pointer
   over a mark is always the hand. */
.marks{user-select:none;-webkit-user-select:none}
.marks a{display:block;color:inherit;cursor:pointer}
.marks img{-webkit-user-drag:none}
/* Every logotype is rendered white from whatever the manufacturer published —
   black, gold or already white — so the strip needs one file per brand rather
   than a light and a dark one. Height is set per logo, not per row: the marks
   carry very different amounts of ink, and a common height would make the
   heavy ones shout. Each --h is the height at which that logo's ink area
   matches the median of the sixteen, measured by rasterising all of them at one
   height and counting alpha-weighted coverage.

   That rule was written for wordmarks, and it breaks on a stacked mark: a tall
   lockup carries little ink for its height, so equalising ink asks for 53px of
   Goldmund and 85px of Esprit in a row whose base is 26. The measurement is
   therefore clamped to 42px. Goldmund, Esprit and EMT sit at that ceiling and
   are the three that would be better served by a horizontal lockup, which is
   part of what the media-kit request to each brand should ask for. */
.marks img{
  display:block;height:calc(var(--h,26px) * var(--mark-scale,1));width:auto;
  filter:brightness(0) invert(1);opacity:.72;transition:opacity .2s;
}
.marks li:hover img{opacity:1}
.footnote{
  margin-top:24px;font-family:var(--mono);font-size:11px;letter-spacing:.04em;
  color:var(--fg-dim);opacity:.6;
}
.sitefoot{padding-block:clamp(40px,4.6vw,64px) 40px}
/* The footer takes the page's measure rather than the text container's, the way
   the reference's does: five columns of links set at the width of an article
   stand in a huddle in the middle of a wide page, and the rule above them then
   stops well short of where the eye expects the page to end. Same padding as the
   header and the plate, so all three edges line up down the whole page.

   Its own rules are not the page's hairline either. On paper --line is a hint
   between rows of text; here it is the structure of the footer, three bands
   divided twice, and it carries at 1.5px and near-white what it could not carry
   at 1px and 16%. */
.sitefoot .wrap{max-width:none;padding-inline:var(--edge)}
.sitefoot{--line:rgba(255,255,255,.72);--line-w:1.5px}
/* The mark stands centred over the whole footer with the networks in a row
   beneath it — the same column a phone always had, now the composition at
   every width, so the footer opens the way the masthead does: the mark first,
   on the page's centre line, and everything else under it.

   Larger than it was at the left edge, because a mark in the middle of a wide
   dark band carries the band, and at 168px it stood in it like a stamp. */
.foot-top{
  --logo-foot:clamp(105px,9.45vw,148px);
  display:flex;flex-direction:column;align-items:center;gap:clamp(22px,2.4vw,32px);
  padding-bottom:clamp(30px,3.4vw,46px);border-bottom:var(--line-w) solid var(--line);
}
/* aspect-ratio rather than a stated height: the drawing is 682 by 402 and a
   rounded height would letterbox it inside its own box. */
.logo--foot{width:var(--logo-foot);height:auto;aspect-ratio:682/402}
.social{display:flex;gap:34px}
@media (max-width:700px){.social{gap:26px}}
/* No ring: the glyphs carry themselves at this size. Which means the line
   weight has to do the work the ring was doing — 2px, the same stroke as the
   masthead icons, on a glyph large enough to hold it.

   Sitting them on a line is not the same as sitting their boxes on it. Each of
   these four drawings stops somewhere different inside its 24-unit box — the
   Instagram square at 21.4, the play button at 19.4 — so aligning the boxes
   leaves the glyphs scattered over two and a half pixels and none of them on
   the line. Each is pushed down by its own shortfall instead, stated on the
   element as the fraction of the box its ink actually reaches. The boxes do not
   move, so nothing reflows; only the drawing does. */
.social li{display:grid;place-items:center}
.social a{
  display:grid;place-items:center;color:#fff;opacity:.72;transition:opacity .2s;
  transform:translateY(calc((1 - var(--ink,1)) * var(--soc)));
}
.social a:hover{opacity:1}
/* Larger glyphs, at the same rendered weight. The drawing is a 24-unit box with
   a 2px stroke; showing it at 30px would scale that stroke to 2.5 and the icons
   would come out heavier than the masthead's, which are the same drawings. The
   stroke is taken down by the same factor instead — 2 x 24 / 30. */
.social{--soc:30px}
.social svg{width:var(--soc);height:var(--soc);display:block;stroke-width:1.6}
/* The five columns run rule to rule, and the air between them is what is equal
   rather than the columns themselves. Five equal fractions of a footer this wide
   looked pushed left — not because they were, but because the text inside each
   is set from its left edge, so the last column's lines stopped well short of
   the right rule while the first heading stood against the left one. Columns as
   wide as their own longest line, spaced apart evenly, put ink on both rules and
   the group sits square under the page.

   Not the same as centring them: centring would have pulled the five together
   into a huddle in the middle and left the width of the footer doing nothing. */
.foot-cols{
  /* The rules take the page; the links take the measure. 1240 is the page's own
     text container, so the columns are inset from the rules by exactly what
     every other block of reading on the site is inset by — a relationship
     rather than a percentage picked to look right at one width. */
  max-width:1240px;margin-inline:auto;
  display:flex;flex-wrap:wrap;justify-content:space-between;
  gap:34px 40px;padding-block:34px 30px;
}
@media (max-width:860px){.foot-cols{justify-content:flex-start;gap:34px 52px}}
/* On a phone the row packs to the left and leaves a hole where the fifth group
   would have been, because five natural-width columns wrapping into 390px are
   three and then two. A grid instead: two columns of equal share, so the block
   has two edges rather than one, and the fifth group takes the full width and
   lays its links across it. That is the group with nowhere to sit in an even
   grid, and a line closing the block reads better than a gap in the corner. */
@media (max-width:700px){
  .foot-cols{display:grid;grid-template-columns:1fr 1fr;gap:30px 20px}
  .foot-cols > div:last-child{grid-column:1 / -1}
  .foot-cols > div:last-child ul{display:flex;flex-wrap:wrap;gap:0 26px}
}
/* The same heading the menu sheet uses — the footer and the menu are the same
   five columns of the same site, and a reader who has opened one should not have
   to learn the other. Only the colour is the footer's own: the sheet sits over a
   photograph and states its grey outright, while here the dark section already
   has a token for text that is not the main line. */
.foot-cols h3{
  font-family:var(--ui);font-size:10.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--fg-dim);margin-bottom:16px;
}
.foot-cols li a{display:block;font-size:13.5px;line-height:2.05;color:var(--fg-dim);transition:color .2s}
.foot-cols li a:hover{color:var(--fg)}
/* Three things on one line: the copyright at the left rule, the policies at
   the right one, and the registration line between them — set in the mono and
   dimmed, so it reads as the small print it is and not as a third heading. It
   takes whatever width the two ends leave and centres in it.

   Where that width runs out the line drops under the other two rather than
   squeezing them: the copyright and the policies stay on their rules, and the
   small print closes the page on a row of its own. */
.foot-legal{
  border-top:var(--line-w) solid var(--line);padding-top:20px;display:flex;flex-wrap:wrap;
  align-items:baseline;justify-content:space-between;gap:12px 28px;font-size:12.5px;color:var(--fg-dim);
}
.foot-legal > span{white-space:nowrap}

/* ============================================================
   Brand page — the parts every brand page has

   Six artefacts, and the page is built so that five of them are what a brand
   record must supply and the sixth is allowed to be missing: logotype, hero
   photograph, slogan, description, one secondary picture — and the range, which
   only exists where the manufacturer publishes series and we hold pictures of
   them. Sixteen brands will not all clear that last bar; the page has to be
   right for the ones that do not.
   ============================================================ */

/* The manufacturer's own mark, in place of its name set in our type. A brand
   page is the one page on the site where the maker speaks in its own voice, and
   the logotype is the first word of it. Rendered white from whatever the
   manufacturer published, the same way the footer strip does — one file per
   brand rather than a light one and a dark one. */
/* Sized by what is written in it, not by the file's own height. The lockup is
   1598 by 343: the circle fills the full height and the wordmark's capitals are
   166 of it, which is 48.4%. Matched to the file, the name comes out at half the
   size of a heading in the same place — which is what "the logotype looks small"
   actually is. So the height is set from the caps instead: the display heading
   here runs to 54px, a capital of it is about 39, and 39 over 0.484 is 80. */
/* One height for every mark, times the brand's own factor where the strip
   draws it larger or smaller than the default — a near-square mark at a
   wordmark's height is a fifth of its width. `brand_mark_scale()` sets it. */
.brandmark{
  height:calc(clamp(34px,4.2vw,58px) * var(--mark-scale,1));width:auto;display:block;
  filter:brightness(0) invert(1);
}
/* The same mark in ink. brightness(0) alone, with no invert after it: it takes
   whatever the manufacturer published — white, gold or black — down to black and
   leaves the transparency alone, so one file serves both grounds. */
.brandmark--ink{
  filter:brightness(0);opacity:.82;
  height:calc(clamp(34px,3.4vw,52px) * var(--mark-scale,1));
  margin:0 auto;
}

/* К6, with a picture in it. The block is the maker's story, and the second
   photograph belongs to the story rather than to the range — a workshop, a
   detail, a person — so it sits inside the block and not in a band of its own.
   Half the width and none of the drama: this is the one picture on a brand page
   that is allowed to be small. */
.brandtell{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:clamp(28px,4vw,80px);align-items:start;
}
@media (max-width:900px){.brandtell{grid-template-columns:1fr}}
.brandtell__figure{margin:clamp(24px,2.6vw,38px) 0 0;position:relative;isolation:isolate}
.brandtell__figure img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block}
/* The caption sits in the overhang, not on the picture. The strip the plane
   leaves below the image is exactly one --plane tall and is otherwise empty, so
   the line goes there: centred across that height, and starting on the image's
   own left edge rather than on the figure's, which is one overhang further out.
   It carries no ground of its own — the plane underneath it is the ground, and
   a panel drawn on top of a panel is one of them for nothing. */
.brandtell__figure figcaption{
  position:absolute;left:var(--plane);right:0;bottom:0;height:var(--plane);
  display:flex;align-items:center;
  color:var(--ink);opacity:.62;
  font-family:var(--mono);font-size:10px;letter-spacing:.08em;
  text-transform:uppercase;
}
/* The plane belongs to the photograph, not to its caption — the picture is the
   panel here, exactly as the panel is the panel on a feature band, and the
   caption is a label on it. The room the plane needs is taken out of the picture
   rather than added around it: the figure keeps its width and the image is inset
   by one overhang on the two sides the plane comes out of, so the block below
   the title stays where it was and the photograph is a little smaller.

   Down and out rather than up. On a band the panel sits on the middle of a
   full-bleed picture and the plane can climb into it; a plane thrown up from a
   picture in a column would leave the column. Six points and one length, as on
   the band, only mirrored — the L keeps the bottom strip and the side strip, and
   at --open 1 the same polygon closes into a whole rectangle.

   Denser than the band's .2: the band veils a photograph chosen to be dark
   enough to carry white text, and this one can land on concrete in daylight,
   where a fifth of white is nothing at all. */
.brandtell__figure{
  --plane:clamp(22px,2.6vw,40px);--open:0;
  --cut:calc(var(--plane) + (100% - var(--plane)) * var(--open));
  padding:0 0 var(--plane) var(--plane);
  /* The plane arrives from the right, two overhangs out, and until it has
     arrived it stands past the figure's edge — which on a 360px phone was
     six pixels past the page's edge too, and a page six pixels wider than
     the window scrolls sideways. The figure clips what crosses its box; at
     rest the plane is inside the box, so nothing of the settled figure is
     lost. Found on 21 September 2026 walking the seams. */
  overflow:clip;
}
.brandtell__figure::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  background:rgba(255,255,255,.55);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  transform:translate3d(var(--travel,0px),0,0);
  inset:var(--plane) var(--plane) 0 0;
  clip-path:polygon(0 0,var(--cut) 0,
    var(--cut) calc(100% - var(--cut)),100% calc(100% - var(--cut)),
    100% 100%,0 100%);
}
/* On a white section the plane is drawn rather than veiled — white on white
   is no plane at all. The Services story, since 21 September 2026, is the
   first figure drawn there; the maker's on the brand page stands on paper and
   keeps the white. The same distance from the ground either way.

   It was the paper until 23 September 2026 and is a neutral grey now, at the
   project owner's word: beside a photograph on white the warm ground read as
   a card of its own colour rather than as the picture's own shadow. */
.section--white .brandtell__figure::before{background:var(--plane-ground);-webkit-backdrop-filter:none;backdrop-filter:none}/* The title is centred and the label above it is not. They are not the same
   kind of thing: THE MAKER says which block this is and belongs on the margin
   with every other label on the page, while the line under it is the maker's
   own sentence and is set as a statement rather than as a heading of a column.

   The prose is justified, and justified text needs hyphenation or it makes its
   own holes. The section carries lang="en", which is what tells the browser
   which language's rules to break the words by — without it the property is
   accepted and does nothing. */
.brandtell__title{text-align:center}
.brandtell__text p{text-align:justify;hyphens:auto}
.brandtell__text p + p{margin-top:14px}
/* The source credit under the maker's mark. Apparatus rather than text: it has
   to be findable, not read, so it takes the mono face at its smallest and the
   dim ink. Centred on the mark above it, which is centred in the column rather
   than on the page. The rule under the link is the only thing marking it as
   one — an accent colour here would make a credit compete with the actions. */
/* Written as a descendant of .brandtell__text, not on its own: the block sets
   text-align:justify on every p it contains, which is the more specific of the
   two and wins — and justify on a single short line is indistinguishable from
   left, which is what put this at the far side of the column. */
/* The mark and its credit follow the story at one distance, the same on
   every brand page: the last line to the mark, and the mark to the credit,
   are both `--sign-gap` — asked for on 20 September 2026. Until then the
   column was stretched to the picture's height and the mark centred in what
   the story left free, which put it 86px under the text on one brand and
   40px on another, since the story runs 300 to 500 words. The column now
   ends where its credit ends, and the picture beside it is as tall as it is. */
.brandtell__text{display:flex;flex-direction:column;--sign-gap:clamp(80px,7.2vw,112px)}
.brandtell__sign{display:flex;flex-direction:column}
.brandtell__sign .brandmark--ink{margin-block:var(--sign-gap)}
/* The words in place of a mark, in ink: the strip's wordmark half as large
   again — a signature under two paragraphs stands larger than a mark in a
   row of sixteen — at the mark's own opacity, centred where the mark would
   stand. No filter — it is type. */
.brandmark--word{
  height:auto;filter:none;font-family:var(--ui);font-weight:300;font-size:39px;
  line-height:1;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);
  opacity:.82;text-align:center;margin-block:var(--sign-gap);
}
/* A brand with no mark — TIDAL for Bugatti, whose lockup is licensed and
   not yet supplied — signs with the credit alone, at the same distance under
   the last line as a mark would stand. */
.brandtell__sign .brandtell__source:first-child{margin-top:var(--sign-gap)}
.brandtell__text .brandtell__source{
  margin:0;text-align:left;
  font-family:var(--mono);font-size:10px;letter-spacing:.07em;
  color:var(--fg-dim);
}
.brandtell__source a{color:inherit;text-decoration:none;
  border-bottom:1px solid var(--line);transition:color .2s,border-color .2s}
.brandtell__source a:hover{color:var(--accent);border-bottom-color:var(--accent)}


/* ============================================================
   Ordinary pages — a title on the dark ground, and a column of reading
   ============================================================ */
/* The head clears the fixed masthead by the masthead's own measure, so the two
   cannot drift apart, and adds half a rhythm under it — enough that the title
   is not sitting on the navigation's edge. */
.pagehead{padding-top:calc(var(--mast-h) + var(--rhythm) * .5)}
/* On a desktop the head is a share of the window's height, not of its width
   — asked for on 20 September 2026 for the legal pages, where a 14-inch
   laptop carried the same 547px head as a 27-inch monitor: two fifths of
   the monitor's window, three fifths of the laptop's. The 27-inch figures
   are the ceiling and the proportions are theirs, of a 1310px window: the
   title at 112px, half a rhythm (52px) under the masthead, a rhythm (104px)
   under the title. Only the head's height and the title's size move — the
   title's own token is restated inside the head, so the two-line box that
   holds it follows — and the masthead above keeps its own measure. */
@media (min-width:1081px){
  .pagehead{
    --step3:clamp(52px,8.55svh,112px);
    padding-top:calc(var(--mast-h) + min(var(--rhythm) * .5,4svh));
    padding-bottom:min(var(--rhythm),7.9svh);
  }
  /* And the title stays on one line. A size taken from the window's height
     knows nothing of the column's width: at 112px *Terms & Conditions* is
     1261px of capitals, and the column is 1120px, so the tallest windows —
     a 27-inch monitor — broke the title in two where a shorter 24-inch one
     did not. The column is made the measure: the longest title the site
     carries is 11.26em wide in the display face at this tracking, so a size
     of 8.8 per cent of the column's width holds it on one line, and the
     height's size applies only where it is the smaller of the two. Only the
     legal pages come near the cap; a short title still takes its 112px. */
  .pagehead .wrap{container-type:inline-size}
  .pagehead h1{font-size:min(var(--step3),8.8cqi)}
}
/* Every page's title ends on the same line, whether it takes one line or two.
   The box is two lines of the title's own size — its line-height is .95, so
   1.9em — and the words sit at the bottom of it. A one-line title therefore
   stands where the second line of a two-line title stands, and the three legal
   pages read as three copies of one page rather than three heads at three
   heights.

   Two lines as a floor, not a ceiling: a longer title, or a narrow window, adds
   lines downward and the head grows with them. Written in the title's own em
   rather than in pixels, so it holds at every step of the clamp. */
/* A shade more air between the lines than the hero's headline takes. That one
   is set tight because it is read as a shape; this one is a page's name and a
   reader goes along it, and at .95 the two lines of a name touch. The box that
   holds it follows the same number — two lines, whatever a line is now — so
   every title still ends on one line. */
.pagehead h1{min-height:2em;line-height:1;display:grid;align-content:end}
/* A head with a line under its title — About — is the same head as one
   without: the same height, and the title on the same line as the legal
   pages' titles. The lede hangs under the title's box, into the head's
   bottom padding, which on a desktop is deeper than the lede is; it adds
   nothing to the head. Asked for on 20 September 2026, twice — first that
   the title stand where the others stand, then that the head stay as tall
   as the others. On a phone the padding is not deep enough to hold it, so
   there the lede is in the flow and the head grows by it. */
.pagehead__words{position:relative}
.pagehead__words .body{position:absolute;top:100%;left:0;right:0;margin-top:clamp(10px,1.2vw,18px)}
@media (max-width:700px){
  .pagehead__words .body{position:static;margin-top:clamp(10px,1.2vw,18px)}
}
/* The controls stand at the page's right edge — the line the masthead's button
   and the footer's row end on — not at the text column's, which stops a long
   way short of it on a wide screen and reads as floating rather than aligned.
   That is why they are placed against the section and not against the column
   inside it.

   In the head's far corner, and not beside the title. Beside it they read as
   part of it — a fourth word on the line — and they are not: they are the way
   out of the page, used after it rather than with it. */
/* The sideways drag is the page's, everything else stays the browser's. Without
   this the browser takes the gesture for scrolling the moment it begins and
   cancels the pointer, which is a swipe that works sometimes and looks broken.
   Zoom is left alone deliberately: taking it off a page of legal text to win a
   gesture is not a trade. */
.pagemain{touch-action:pan-y pinch-zoom}
.pagehead{position:relative}
.pagenav{
  position:absolute;right:var(--edge);bottom:clamp(18px,2.2vw,34px);z-index:2;
}

/* The marks under the head, on a phone. Drawn on paper rather than on a
   photograph, so they take the section's ink the way the brand rail's marks do
   — white on a darkened picture reads heavier than it is drawn, and the same
   grey here would come out the fainter of the two.

   A small step above the reading and a larger one below it: they belong to the
   head they sit under, not to the first line of the clause. */
.pagedots{display:none;margin-bottom:clamp(22px,3vw,34px)}
.pagedots .dot{background:var(--fg);opacity:.28;cursor:default}
.pagedots .dot[data-active]{opacity:1;height:5px;border-radius:3px}

/* The phone. Written here, after the rules it overrides, because a media query
   is not more specific than anything — it only comes later, and this one was
   sitting two hundred lines above the `display:none` it was meant to undo. */
@media (max-width:700px){
  /* The arrows come off and the gesture takes their place: a page that can be
     swiped does not need a button saying so, which is the reading the landing
     slider already takes at this width. What is left is the marks — they say
     how many there are and which one this is, and no gesture says that. */
  .pagenav{display:none}
  /* Centred. The marks are a position in a set of three, and a set of three is
     read as a whole — hung on the left margin they read as the first thing in
     the column instead. */
  .pagedots{display:flex;justify-content:center}
  /* The title comes down with the window. `--step3` bottoms out at 52px, which
     is a headline's floor on a wide screen and a wall on a 390px one: the name
     of a page should not be the whole of the first view. */
  .pagehead h1{font-size:clamp(30px,9vw,44px)}
}
/* The slider drops its arrows on a phone because the picture can be dragged
   instead. There is nothing to drag here, so they stay: they are the only way
   forward on a page that has no other. */


/* Half a rhythm under the head rather than a whole one. A full one is the
   distance between two sections that are about different things; the date and
   the title above it are the same statement, and the page reads as broken in
   two at that size. */
.pagebody{padding-top:calc(var(--rhythm) / 2)}

/* The head's ground, where the library has a picture for it. It is the hero's
   backdrop construction without the hero: the same oversizing so the blur has
   material to sample at the edges instead of fading into the corners, and the
   same reasoning — a photograph destroyed past its subject is a ground with
   depth in it, which flat black is not.

   Two differences from the hero, both because nothing here is measured. The
   hero lifts its backdrop towards white and lets the script dim it per picture,
   because a bright photograph would swallow the white masthead; this has no
   script and no picture chosen for it, so it takes a fixed scrim heavy enough
   that any photograph put in the library still leaves the navigation and the
   title readable. Whoever changes the picture is choosing a ground, not
   re-testing whether the page works. */
.pagehead--picture{position:relative;overflow:hidden}
.pagehead__backdrop{
  position:absolute;inset:-70px;
  background-size:cover;background-position:center;
  /* Contrast before brightness, and both after the blur. The blur is an average
     — it pulls every lit part of the picture towards the middle, which is what
     made the ground read as one flat tone. Contrast pushes them back apart,
     brightness lifts what is left. Raising brightness alone would only have
     made the whole thing paler. */
  filter:blur(48px) contrast(1.28) brightness(1.16);
}
/* Denser under the title than at the top, so the two lines of the masthead sit
   on the lighter half and the heading on the heavier one.

   Lighter at both ends than it was. The scrim is what stops a bright
   photograph from swallowing the white masthead, and set heavy enough for the
   worst case it also flattened the best one: the lit parts of the picture, the
   only thing a 48px blur leaves worth looking at, were being pushed down to
   the same value as the dark. */
.pagehead--picture::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(
    color-mix(in srgb,var(--night) 38%,transparent),
    color-mix(in srgb,var(--night) 62%,transparent));
}
.pagehead--picture > .wrap{position:relative;z-index:1}
/* The same head turned down — Services, since 21 September 2026, whose
   picture is the landing's warm room and blurred to amber. The blur keeps
   its contrast and loses its lift, and the scrim is heavier at both ends, so
   the ground is the room's colour at night rather than in the afternoon.
   Brought halfway back up the same day — the first cut was too dark. */
.pagehead--deep .pagehead__backdrop{filter:blur(48px) contrast(1.28) brightness(.95) saturate(.9)}
.pagehead--deep::after{
  background:linear-gradient(
    color-mix(in srgb,var(--night) 46%,transparent),
    color-mix(in srgb,var(--night) 68%,transparent));
}

/* Everything inside comes from the editor, so it is addressed by element rather
   than by class: a page whose author never learns a class name is a page that
   stays correctly set after they have edited it.

   The block takes the whole width, because the clauses are a two-column
   composition, and the lines that open the document take it with them: a
   paragraph stopped at the reading measure above a row that runs to the edge
   reads as two pages rather than one. */
/* The page that is not there: the ordinary page's body with two sentences
   and one button in it. The text keeps to a reading measure — the body is not
   a document, as the legal pages are, and a line the whole page wide would be
   a long way to read that nothing is here. */
.notfound .body{max-width:56ch;margin-top:14px}
/* Two and a half times the height its words need, at the project owner's
   word of 17 September 2026: the white keeps the page's proportion under
   the head, where a body only as tall as three lines and a button read as a
   footer arriving early. The words stand in the middle of it. */
/* The same padding above and below — the ordinary page body halves the top,
   which would put the centre of this one above the middle. */
.notfound--white{min-height:clamp(480px,50vw,760px);padding-block:var(--rhythm);display:grid;align-content:center}
/* The band candidates: the brand band's own construction, as tall as the
   white body is, the panel in the middle of it. */
.notfound--band .band__inner{min-height:clamp(480px,50vw,760px)}
.pagehead--centred h1{text-align:center}
.notfound__actions{display:flex;gap:11px;flex-wrap:wrap;margin-top:30px}

.prose{max-width:none}
/* Full ink, not the dimmed colour the site uses for supporting copy. This is a
   document somebody has to read from the top to the end — often because they
   were told to — and .66 alpha is a treatment for text nobody is expected to
   finish. */
.prose p{color:var(--fg)}
.prose > * + *{margin-top:16px}
/* The date the text took effect. It is the first thing a reader looks for and
   the one line on the page that is not part of the document, so it is set as a
   label rather than as a sentence — the same label every other part of the site
   uses to say what a thing is. */
/* Written as a descendant of .prose, not on its own: `.prose p` sets the ink
   for every paragraph in the block and is the more specific of the two, so a
   class alone would lose the colour it exists for. */
.prose .prose__updated{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--accent);
}

/* Lets a height animate to and from `auto`, which is the whole difficulty with
   opening a box whose content decides its own size. Declared once, and read
   only where something actually transitions to a keyword. */
:root{interpolate-size:allow-keywords}

/* Fourteen clauses, each shut until it is asked for.
   `<details>` rather than a script: the browser already has this behaviour, it
   is keyboard-operable and announced correctly without being told to be, and
   find-in-page opens a closed clause on its own. A version written in
   JavaScript would have to be given all three, and would be wrong on the page
   where being wrong matters most.
   The rows are separated by rules rather than by air. A legal document is a
   list of clauses, and a list with a line between each row is the form the
   reader already knows from every table of terms they have read before. */
.prose details{
  position:relative;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  column-gap:clamp(28px,4vw,80px);align-items:start;
  border-top:1px solid var(--line);
}
.prose details:last-of-type{border-bottom:1px solid var(--line)}
.prose > * + details{margin-top:clamp(28px,3vw,44px)}
.prose > details + details{margin-top:0}

/* The clause name, set as the slider sets a name: the interface face at its
   lightest weight, in capitals, tracked open. The size is half the page
   headline's — the same voice one level down. Capitals are the design's, not
   the editor's: the summary holds a sentence and this decides how it is set. */
.prose summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:baseline;
  padding-block:clamp(14px,1.5vw,20px);
  font-family:var(--ui);font-weight:300;
  font-size:clamp(15px,1.7vw,23px);line-height:1.2;
  text-transform:uppercase;letter-spacing:.04em;
  /* The colour arrives across the name rather than on all of it at once. Two
     halves of one image twice the row's width — the accent on the left, the
     page's ink on the right — clipped to the letters and slid from one half to
     the other. The letters themselves carry no colour, which is why the marker
     has to be given its own back below. */
  background-image:linear-gradient(to right,var(--accent) 50%,var(--fg) 50%);
  background-size:200% 100%;background-position:100% 0;background-repeat:no-repeat;
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  transition:background-position .45s cubic-bezier(.4,0,.2,1);
}
/* Hover only. Holding the accent on an open clause left one name coloured and
   thirteen not, which reads as one row having been treated differently rather
   than as one row being open — the sign at the edge already says which is
   which. Every name is now the same until a pointer is on it. */
.prose summary:hover{background-position:0 0}
/* Where a system paints its own colours, a transparent fill is an invisible
   heading. The wipe is a decoration; the name is not. */
@media (forced-colors:active){
  .prose summary{color:CanvasText;-webkit-text-fill-color:CanvasText}
}
.prose summary::-webkit-details-marker{display:none}

/* The sign that says the row opens, at the far edge of the page and taken out
   of the flow to get there. It was at the end of the name first, which aligned
   it to nothing — every name is a different length, so it landed mid-page, in a
   different place on every row. An edge is a thing to align to; the middle of a
   column is not. Positioned rather than pushed, because the name and the clause
   are the two columns of the row and the sign cannot be a third without one of
   them giving up its place. A plus that becomes a minus, in the interface face
   — the clause name is the document's language and this is the site's. */
.prose summary::after{
  content:"+";position:absolute;right:0;top:clamp(14px,1.5vw,20px);
  font-family:var(--ui);font-size:19px;font-weight:300;line-height:1.2;
  /* Grey, not the accent. The sign is a mark of state — shut, open — and the
     accent on this page belongs to the labels: the date at the top and the
     named parts inside a clause. Grey also puts it at the same value as the
     mark beside a list item, which is drawn with the same glyph at the same
     size: one mark on the page rather than two that nearly match. */
  color:var(--fg-dim);-webkit-text-fill-color:var(--fg-dim);
}
/* Under the pointer it comes up to full ink with the name beside it. */
.prose summary:hover::after{color:var(--fg);-webkit-text-fill-color:var(--fg)}
/* The true minus, U+2212, not the en dash it was. The dash is a piece of
   punctuation — thinner, shorter and sitting on a different line — while
   this glyph is drawn as the plus’s counterpart: same width, same stroke,
   same height on the same axis. It is in the latin subset the theme ships,
   so nothing new is loaded for it. */
.prose details[open] summary::after{content:"−"}
/* The clause opens beside its name rather than under it — the composition the
   maker's story is built in on the brand page: what the thing is called on the
   left, what there is to say about it on the right. Both are row one of the
   same grid, so a clause that opens pushes nothing sideways and the rules
   between clauses stay the width of the page.

   Set as that story is set: both edges flush, hyphenated. Justification needs a
   column narrow enough to break badly and a dictionary to stop it, and the
   second is why this is safe here — the page declares its language. */
.prose details > summary{grid-column:1;grid-row:1}
.prose .clause{
  grid-column:2;grid-row:1;
  /* A line below the name. Justified text reaches the right edge exactly, which
     is where the sign is, so a first line level with the name would run into
     it. */
  padding-block:calc(clamp(14px,1.5vw,20px) + 1.9em) clamp(20px,2.2vw,30px);
}
/* The list items are set as the paragraphs are. A clause that justifies its
   prose and leaves its list ragged is two settings of one voice, and the list
   is the half a reader compares items down — a straight right edge is worth
   more there than in a paragraph, not less. */
.prose .clause :is(p,li){text-align:justify;hyphens:auto}
/* A named part inside a clause — a kind of cookie, a kind of information held.
   It is a label rather than a heading: the clause name above it is already the
   heading, and a second one at that size would compete with it. So it is set as
   the page's other label is set, the date at the top: same face, same size, same
   tracking, same accent. One label, used twice, rather than two labels a reader
   has to tell apart. */
.prose .clause h4{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--accent);line-height:1.5;text-align:left;
}
/* A short rule between paragraphs rather than air alone. A clause is a run of
   separate statements, not one argument, and the reader needs to see where one
   ends — but a rule across the column would divide the clause into pieces that
   look like clauses of their own. A quarter of the width marks the join without
   claiming to be a heading. */
/* Written as a descendant, not as a child. The group puts its own inner
   container between itself and the paragraphs, so a child selector reaches one
   box and stops — which is why the gap this replaces never appeared. */
.prose .clause :is(p,ul,ol,h3,h4) + :is(p,ul,ol,h3,h4){
  position:relative;margin-top:22px;padding-top:22px;
}
.prose .clause :is(p,ul,ol,h3,h4) + :is(p,ul,ol,h3,h4)::before{
  content:"";position:absolute;inset:0 auto auto 0;width:25%;
  border-top:1px solid var(--line);
}
/* One column below the width the two of them stop being two columns in. The
   same measure the brand page's story uses, for the same reason. */
/* The opening itself. The browser now gives the shut content a box of its own,
   and a box can be given a height to travel — from nothing to as tall as the
   clause is, and back down again on the way out. `content-visibility` has to
   travel with it, or the content would vanish at the start of the close instead
   of at the end of it.
   Where a browser does not make that box, none of this applies and the clause
   opens the way it opened before: at once. Nothing else changes, because the
   placement is stated on the clause itself as well. */
.prose details::details-content{
  grid-column:2;grid-row:1;
  block-size:0;overflow:hidden;
  transition:
    block-size .72s cubic-bezier(.22,.35,.03,1),
    content-visibility .72s allow-discrete;
}
.prose details[open]::details-content{block-size:auto}

@media (max-width:900px){
  .prose details{grid-template-columns:minmax(0,1fr)}
  .prose details::details-content{grid-column:1;grid-row:auto}
  .prose details > summary,.prose .clause{grid-column:1}
  .prose .clause{grid-row:auto;padding-top:0}
}

/* Kept for a page that is prose rather than clauses. */
.prose h2{
  font-family:var(--ui);font-size:13.5px;font-weight:500;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent);line-height:1.5;
}
.prose h3{
  font-family:var(--ui);font-size:var(--step0);font-weight:500;
  letter-spacing:.02em;color:var(--fg);line-height:1.5;
}
/* A clause opens further from the one that ended than its own heading stands
   from its first line — the gap is what says a new clause has started. */
.prose > h2 + *{margin-top:12px}
.prose > * + h2{margin-top:44px}
.prose > * + h3{margin-top:28px}
.prose > h2:first-child,.prose > h3:first-child{margin-top:0}
/* A dash rather than a disc. The clauses are a run of statements, and the rule
   between paragraphs is already drawn as a line — a round mark beside them is
   the one shape on the page that belongs to no other part of it. Drawn as a
   character in the flow rather than with `::marker`, whose `content` is not
   understood everywhere, and the dash is the en dash: the shorter one is a
   hyphen joining words and this joins nothing. */
.prose ul,.prose ol{padding-left:22px;color:var(--fg)}
.prose ul{list-style:none;padding-left:0}
.prose ul li{position:relative;padding-left:1.5em}
/* The same sign the accordion opens with, drawn the same way: U+2212 in the
   interface face at the size and weight the clause rows use, so the two marks
   on the page are one mark. Grey rather than the accent — the accordion sign
   is something to press and this is not, and a mark that looks pressable
   beside text nobody can press is a promise the page does not keep. The line
   box is matched to the line the item starts on, not to the glyph. */
.prose ul li::before{
  content:"−";position:absolute;left:0;top:0;
  font-family:var(--ui);font-size:19px;font-weight:300;line-height:1.5;
  /* Nearer the rule between paragraphs than the text: both are the page's own
     lines rather than anything a writer put there — one says a new item starts,
     the other says a new statement does — and at the text's value the mark read
     as a word with nothing after it. Not all the way down to the rule either. A
     rule is a long shape and carries at a value a single short one disappears
     at, so this sits between the two: light enough to be a mark, dark enough to
     be seen. */
  color:color-mix(in srgb,var(--fg) 34%,transparent);
}
.prose ol{list-style:decimal}
.prose li + li{margin-top:6px}
.prose a{
  color:var(--accent);
  border-bottom:1px solid color-mix(in srgb,var(--accent) 40%,transparent);
  transition:border-color .2s;
}
.prose a:hover{border-bottom-color:var(--accent)}
.prose strong{font-weight:500}

/* ============================================================
   The About page — the two constructions it has that no other page does
   ============================================================ */
/* The About page's values are the brand page's range, since 20 September
   2026 — same head, same rail, same cards — with one difference: the cards
   are not links, so the picture does not move under the pointer. */
.cardwall--still .card:hover img{transform:none}

/* The closing: two lines and one action, centred on the dark ground — the
   place the proposal ends the page, and the one block here whose words are
   the subject rather than a picture. Centred because there is nothing beside
   it to be aligned to. The measure is wider than the body's 60ch because the
   type is larger, and the second line takes the accent for the reason
   `render_about_closing()` gives: it is the turn, and the theme has no italic
   to set it in. */
.closing{text-align:center}
.closing .wrap{max-width:900px}
.closing h2.display{font-size:var(--step2);line-height:1.2}
.closing__turn{
  font-size:var(--step2);line-height:1.2;color:var(--accent);
  margin-top:.35em;
}
.closing .button{margin-top:clamp(28px,3.4vw,48px)}
/* The same block between the landing's two bands, and shorter there. On About
   it is the page's last word and takes the section rhythm every other section
   takes; on the landing it is a breath between two full-bleed pictures, and a
   pause that takes as much room as a closing reads as a section of its own
   rather than as the quiet between two. About two thirds of the rhythm, which
   on a 23-inch screen is 58px of air above and below instead of 104. The type
   and the measure are untouched: it is the same two lines, and a second size
   for them would make it a second block. Project owner, 22 September 2026. */
.closing--tight{padding-block:clamp(34px,3.6vw,58px)}
/* And a measure that holds the first sentence to two lines at every width. The
   closing's own 900px was set against type that stops growing at 46px, and the
   two stop at different places: up to about 1200px the sentence takes two
   lines, and from 1353 — where the type reaches its ceiling and the measure
   reached its own long before — it takes three. Three lines over two is not a
   worse line break, it is a different block: the shape the project owner asked
   for, and showed, is four lines of type. 1020px is where the sentence fits at
   46px; below 1020 the wrap is the page's width and nothing changes. Measured
   in a browser, 22 September 2026. */
.closing--tight .wrap{max-width:1020px}

/* ============================================================
   Services page — the row of names; and the split the showrooms index kept
   ============================================================ */
/* The row of four names: the page's own table of contents, on paper between
   the story and the first band. The same label as every other small word on
   the site, and nothing else — a strip, not a section. The introduction it
   stood under came off on 20 September 2026, when the page was redrawn on
   the About page's constructions; the split below it stays for the showrooms
   index, which is drawn on it. */
/* Four words in white — the accent until later the same day — centred on the night — the strip went from
   paper to the dark ground at the project owner's word of 21 September
   2026, so it is the bands' ground reaching up rather than a light strip
   between the story and them. Each word on a cell of its own that shows
   only under the pointer — the project owner's own idea the same day, with
   the pointer's answer drawn on the ground rather than on the word: the
   cell under the pointer comes up a shade lighter than the night, from its
   foot, the word on it rises and turns white, and the other three words go
   out. The cell's ground is drawn on a layer under the word and scaled up
   from the bottom edge, so it arrives as a movement and not as a switch.
   At rest the row is as it was, the cells' side padding being the distance
   between the words — a little more of it than the gap gave.

   And the row moves. With the pointer on it the four cells grow to share
   the page's width — the row's own layout of a moment earlier, kept as
   where the motion goes — and settle back to the centred row when it
   leaves; the project owner's word of 21 September 2026. Growth is a
   flex-grow transition, which the browser animates, and the row's side
   padding goes with it so the outer cells reach the edges. Slow — three
   times what the first cut was, at the project owner's word the same day,
   asked for twice — and on a symmetric curve, easing in as well as out:
   on the site's usual ease-out the spread had most of its travel in the
   first tenth of a second and read as quicker than the settling back,
   though the two took the same time. The settling back is then quicker
   than the spread — the duration on the hover rule is the way in, the one
   on the rest rule the way out. */
.servicenav{background:var(--night);color:#fff}
.servicenav ul{
  display:flex;flex-wrap:wrap;justify-content:center;padding-inline:var(--gutter);
  transition:padding .8s cubic-bezier(.65,0,.35,1);
}
.servicenav ul:hover{padding-inline:0;transition-duration:1.4s}
.servicenav li{display:flex;flex:0 1 auto;transition:flex-grow .8s cubic-bezier(.65,0,.35,1)}
.servicenav ul:hover li{flex-grow:1;transition-duration:1.4s}
/* The four names in the kicker's own face and colour — the accent of *Our
   services* above them, asked for on 21 September 2026, and five pixels over
   the kicker's size, asked for the same day; until then they were a step
   smaller and dim. */
.servicenav a{
  position:relative;isolation:isolate;flex:1;
  display:grid;place-items:center;text-align:center;
  padding:clamp(14px,1.4vw,20px) clamp(18px,2.4vw,40px);
  font-family:var(--ui);font-size:17.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:#fff;
  transition:color .9s;
}
.servicenav a::before{
  content:"";position:absolute;inset:0;z-index:-1;background:var(--white);
  transform:scaleY(0);transform-origin:bottom;
  transition:transform 1.1s cubic-bezier(.22,.35,.03,1);
}
.servicenav a > span{display:block;transition:transform 1.1s cubic-bezier(.22,.35,.03,1)}
/* The cell under the pointer is white and its word ink — the Auditions
   strip's answer, brought back to Services on 22 September 2026; until
   then the cell came up a shade lighter than the night with the word white. */
.servicenav ul:hover a{color:rgba(255,255,255,.28)}
.servicenav ul:hover a:hover{color:var(--ink)}
.servicenav a:hover::before{transform:scaleY(1)}
.servicenav a:hover > span{transform:translateY(-2px)}
@media (prefers-reduced-motion:reduce){
  .servicenav ul,.servicenav li,.servicenav a::before,.servicenav a > span{transition:none}
}
/* The words under the choice change as the hero's slides do — the block for
   the way chosen drives in from the side the choice moved towards, and the
   one leaving drives out the other way, on the slides' own curve and time.
   The project owner's word of 21 September 2026. The leaving block is
   lifted out of the flow so the two overlap, and the wrap is held to the
   arriving block's height for the crossing, which the script measures —
   see the choice in site.js. The wrap clips what crosses its edge; at rest
   the transform is none, so nothing of a settled block is cut. */
/* The wrap is held to the taller of the two blocks and stays there, so
   pressing the other name moves the words sideways and nothing else — the two
   texts are within a line of each other, and a block that grows and shrinks by
   that line makes the form under it jump. The project owner's word,
   23 September 2026. The script measures both and writes the taller as
   `min-height`; the transition is there for the width changing under it, not
   for the choice. */
.tells{position:relative;overflow:clip;transition:min-height 1.5s cubic-bezier(.22,.35,.03,1)}
.tell{transition:transform 1.5s cubic-bezier(.22,.35,.03,1)}
/* How the hidden block is measured: in the flow's place and at the flow's
   width, but out of the flow and invisible, so measuring costs the page
   nothing and shows nothing. */
.tell.is-measuring{position:absolute;top:0;left:var(--gutter);right:var(--gutter);visibility:hidden}
.tell.is-off{position:absolute;top:0;left:var(--gutter);right:var(--gutter);transform:translateX(-110%)}
.tell.is-off.to-right{transform:translateX(110%)}
.tell.is-in{transform:translateX(110%)}
.tell.is-in.from-left{transform:translateX(-110%)}
@media (prefers-reduced-motion:reduce){.tells,.tell{transition:none}}
/* The choice as the Services page's row of names — the Auditions page under
   the legal pages' head, 21 September 2026, after an hour as two cards on
   paper. The row is the Services strip, and the one chosen stands on the
   lifted cell the pointer would raise, and keeps it; the pointer's own
   answer is the strip's, unchanged. Written after the strip's own rules,
   which it ties on specificity and must therefore follow. */
/* Its own colours, at the project owner's word the same day: the strip a
   grey rather than the night, the chosen name in ink on a white cell — a
   choice reads as a state, and white on grey is a state where a shade
   lighter than the night was a hover. The other name stays white on the
   grey until the pointer is on it, when it takes the same white cell and
   the same ink — what it will be if pressed. */
.servicenav--choice{background:var(--night)}
/* Spread from the start: two names share the strip's width at rest, so the
   chosen one's white runs the whole of its half rather than boxing the
   word — the project owner's word of 21 September 2026. The words keep
   the strip's own motion: at rest they stand together at the strip's
   centre, each at its half's inner edge, as the centred row stood them;
   under the pointer they drive out to the middle of their halves and come
   back when it leaves — the same travel, the same curve, on cells that no
   longer move. The travel is the cell's grid: three columns, the word in
   the middle one, and the outer two trading their share. */
.servicenav--choice ul{padding-inline:0}
.servicenav--choice li{flex-grow:1}
.servicenav--choice a{
  grid-template-columns:1fr auto 0fr;
  transition:color .9s,grid-template-columns .8s cubic-bezier(.65,0,.35,1);
}
.servicenav--choice li:last-child a{grid-template-columns:0fr auto 1fr}
.servicenav--choice a > span{grid-column:2}
.servicenav--choice ul:hover a{grid-template-columns:1fr auto 1fr;transition-duration:.9s,1.4s}
/* On a phone the two are rows, not halves, and the centre of the strip is
   not between them. There the chosen word stands at the right edge and the
   other at the left, and a choice sends each slowly across to the other
   side — the project owner's word of 21 September 2026, from the phone.
   A touch leaves its hover on the row it pressed, so the hover rule is
   put out of the way here; the travel is the choice's, not the pointer's. */
@media (max-width:700px){
  .servicenav--choice a,
  .servicenav--choice li:last-child a,
  .servicenav--choice ul:hover a{grid-template-columns:0fr auto 1fr;transition-duration:.9s,1.4s}
  .servicenav--choice li a[aria-pressed="true"],
  .servicenav--choice ul:hover li a[aria-pressed="true"]{grid-template-columns:1fr auto 0fr}
  .servicenav--choice ul:hover a[aria-pressed="true"]:not(:hover){color:var(--ink)}
  .servicenav--choice ul:hover a[aria-pressed="true"]:not(:hover)::before{transform:scaleY(1)}
  .servicenav--choice ul:hover a:not([aria-pressed="true"]){color:#fff}
  .servicenav--choice ul:hover a:not([aria-pressed="true"])::before{transform:scaleY(0)}
}
.servicenav--choice a::before{background:var(--white)}
.servicenav--choice a[aria-pressed="true"]::before{transform:scaleY(1)}
.servicenav--choice a[aria-pressed="true"],
.servicenav--choice ul:hover a:hover{color:var(--ink)}
/* With the pointer on the other name, the white goes to it and the chosen
   one stands as the other did — the strip shows what a press would make
   of it. Under the pointer itself the chosen one keeps its white. */
.servicenav--choice ul:hover a[aria-pressed="true"]:not(:hover){color:rgba(255,255,255,.28)}
.servicenav--choice ul:hover a[aria-pressed="true"]:not(:hover)::before{transform:scaleY(0)}
/* Each service on its own dark ground, a rule between one and the next. The
   landing's split at the landing's proportion: the words take the narrower
   column and the picture the wider, and every other one swaps sides — the
   columns swap with it, so the picture is the wide column on the left as it
   was on the right. Middle-aligned rather than top, because the picture is
   taller than the words on every laptop and the words should sit beside it,
   not hang from its top edge. Below 860 the split stacks as every split
   does, words first, and the swap comes off with the columns. */
.service + .service{border-top:1px solid var(--line)}
.split--service{align-items:center}
.service--flip .split--service{grid-template-columns:7fr 5fr}
.service--flip .service__figure{order:-1}
.service__words h2.display{font-size:var(--step2);line-height:1.1}
.service__words .body{margin-top:clamp(16px,1.8vw,24px)}
.service__words .button{margin-top:clamp(22px,2.6vw,36px)}
.service__figure{margin:0;position:relative}
.service__figure img{width:100%;aspect-ratio:4/3;object-fit:cover;object-position:var(--focus,center)}
.service__figure--bare{aspect-ratio:4/3;background:var(--night);box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
@media (max-width:860px){
  .service--flip .split--service{grid-template-columns:1fr}
  .service--flip .service__figure{order:0}
}

/* For the document and the reader whose screen is read to them: in the flow,
   off the screen. WordPress's own class name, so a plugin that expects it
   finds it. */
.screen-reader-text{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0,0,0,0);clip-path:inset(50%);border:0;white-space:nowrap;
}
/* The words of the way chosen, in the brand page's story construction. One
   block per way is in the page and the script shows the chosen one; hidden
   has to beat the grid or the attribute does nothing. Under the paragraphs,
   the one action on, and beside it the place, quietly. */
.tell[hidden]{display:none}
.tell__actions{
  display:flex;flex-wrap:wrap;gap:12px 28px;align-items:center;
  margin-top:clamp(24px,2.6vw,36px);
}
.choice__aside{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  text-transform:uppercase;color:var(--fg-dim);transition:color .2s;
}
.choice__aside:hover{color:var(--fg)}
/* The Services construction, extended for the showrooms: the client's tagline
   over his paragraphs, in the serif at the reading size, the way the plate
   sets a tagline under a title. */
.service__tagline{
  font-family:var(--display);font-size:var(--step1);line-height:1.35;
  color:var(--fg);margin-top:clamp(16px,1.8vw,24px);max-width:var(--measure);
}
.service__tagline + p.body{margin-top:clamp(16px,1.8vw,24px)}
/* The showroom page: the words in the narrower column and the visit beside
   them — К12, the card a visitor arrives with. On paper, in a hairline box,
   the lines under each small heading set one under the other; the kicker's
   own margin separates one group from the next. */
.split--visit{grid-template-columns:7fr 5fr;align-items:start}
.showroom__note{font-size:var(--step1);line-height:1.35;margin-top:clamp(20px,2.4vw,32px)}
.visit{
  border:1px solid var(--line);padding:clamp(24px,2.8vw,40px);
  display:grid;gap:8px;align-content:start;
}
.visit .kicker{margin-bottom:0}
.visit .kicker + .visit__lines{margin-bottom:clamp(14px,1.6vw,22px)}
.visit__lines{display:grid;gap:2px;color:var(--fg-dim)}
.visit__lines a{color:var(--fg);text-decoration:none;border-bottom:1px solid var(--line);width:max-content;max-width:100%}
.visit__lines a:hover{color:var(--accent);border-bottom-color:var(--accent)}
.visit .button{margin-top:clamp(10px,1.4vw,18px);justify-self:start}
@media (max-width:860px){.split--visit{grid-template-columns:1fr}}

/* ============================================================
   The Contact page — his three ways, a ruled list, and the map
   ============================================================ */
/* The three ways to reach him, in a row: three hairline boxes, the showroom
   page's visit card three times over, each one a link. The mark stands
   alone on the first line, the way's name under it in the label face, and
   the number or address under that in the reading face — a box is read as
   what it does, then as where it goes. On a phone they stand one under the
   other, each one a row — the mark beside the words rather than over them,
   so three boxes are three lines of a list and not a column of cards —
   and a thumb reaches each. */
/* His sentence runs the width of the cards under it and no wider — one
   line where the row is wide enough, and wrapping at the cards' edge where
   it is not — rather than at the reading measure, which broke it in two
   over a row that had room for it. Asked for on 21 September 2026. */
p.contact__intro{margin-bottom:clamp(28px,3vw,44px);max-width:none}
.ways{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(12px,1.6vw,24px)}
.way{
  display:grid;gap:10px;align-content:start;
  padding:clamp(22px,2.6vw,36px);border:1px solid var(--line);
  background:var(--white);
  color:var(--fg);text-decoration:none;
  transition:border-color .2s,color .2s;
}
.way:hover{border-color:var(--accent)}
.way .kicker{margin:0}
.way__mark{display:block;width:30px;height:30px;color:var(--fg);margin-bottom:8px}
.way__mark svg{width:100%;height:100%;display:block}
/* The number and the address in the accent, as the legal pages set theirs:
   a way to reach him is a link, and the site's links are this colour. Asked
   for on 21 September 2026; until then they were dim and turned only under
   the pointer. The hover is the box's border now, since the words are
   already the colour they would have turned. */
.way__value{font-size:var(--step0);line-height:1.5;color:var(--accent);overflow-wrap:anywhere}
@media (max-width:700px){
  .ways{grid-template-columns:minmax(0,1fr)}
  .way{grid-template-columns:auto minmax(0,1fr);column-gap:18px;row-gap:2px;align-items:center;padding-block:18px}
  .way__mark{grid-row:1 / span 2;margin:0;width:26px;height:26px}
}

/* The rest of his page as the legal pages set their clauses — the name on
   the left in the clause face, what there is to say on the right, a rule
   between rows — with nothing to open, because nothing here is long enough
   to hide. The measures are the clauses' own, restated rather than shared,
   so a change on the legal pages is a change made there on purpose. */
/* The list opens its own section now, so it stands on the section's padding
   rather than on a margin of its own. */
.ledger{margin:0;padding:0}
.ledger__row{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  column-gap:clamp(28px,4vw,80px);align-items:start;
  border-top:1px solid var(--line);
  padding-block:clamp(14px,1.5vw,20px) clamp(20px,2.2vw,30px);
}
.ledger__row:last-child{border-bottom:1px solid var(--line)}
.ledger__name{
  font-family:var(--ui);font-weight:300;
  font-size:clamp(15px,1.7vw,23px);line-height:1.2;
  text-transform:uppercase;letter-spacing:.04em;color:var(--fg);
}
/* The first line of the body sits on the name's line: the name's face is
   larger, so the body is dropped by the difference in their half-leadings. */
.ledger__body{margin:0;padding-top:.2em;color:var(--fg)}
.ledger__body p{color:var(--fg)}
.ledger__body p + p{margin-top:16px}
.ledger__body .visit__lines{color:var(--fg)}
/* The lines that dial and write are the legal pages' links: the accent, on
   the accent's own faint rule. The showroom page's visit card keeps its
   own, which is why this is written against the ledger and not the lines. */
.ledger__body .visit__lines a{
  color:var(--accent);
  border-bottom-color:color-mix(in srgb,var(--accent) 40%,transparent);
}
/* A line's words stand in the page's ink; the link in it, and the hours,
   which are not a link, in the accent. The line itself is the row now, so
   the link inside it takes only its own words' width. */
.ledger__body .visit__lines > span > a{display:inline;width:auto}
.ledger__body .visit__mark{font-style:normal;color:var(--accent)}
@media (max-width:900px){
  .ledger__row{grid-template-columns:minmax(0,1fr);row-gap:10px}
  .ledger__body{padding-top:0}
}

/* The map. A frame the width of the page at the plate's proportion on a
   desktop, taller than wide on a phone, where a strip would show the
   building and nothing to find it by. Under it, until it is asked for, a
   cover on the night ground: the address, the one button, and whose map it
   is — the same words a reader would need if the frame never came. */
.maphead{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  margin-top:var(--rhythm);
}
.maphead .kicker{margin:0}
.map{
  position:relative;margin-top:clamp(14px,1.6vw,22px);
  aspect-ratio:16/7;background:var(--night);border:1px solid var(--line);
  overflow:hidden;
}
.map iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.map__cover{
  position:absolute;inset:0;display:grid;align-content:center;justify-items:center;
  gap:18px;padding:clamp(24px,3vw,48px);text-align:center;color:#fff;
}
.map__lines{display:grid;gap:2px;font-family:var(--display);font-size:var(--step1);line-height:1.35;text-wrap:balance}
.map__note{font-family:var(--ui);font-size:12px;letter-spacing:.04em;color:rgba(255,255,255,.55);max-width:38ch}
@media (max-width:700px){.map{aspect-ratio:4/5}.map__lines{font-size:var(--step0)}}
/* The map in one column of a split, which is where the Auditions page puts it
   under the form. 16:7 is a strip drawn for the width of the body; at seven
   twelfths of it the same ratio is a letterbox with a building in it. Four to
   three is the shape a map wants when it is as tall as the words beside it.
   The head above it loses the section rhythm for the same reason: it is the
   top of a column, not a block following another one, and it stands level with
   the kicker in the column beside it. */
.map--column{aspect-ratio:4/3}
/* Under the map rather than over it, so it reads as a caption. */
.maphead--foot{margin-top:clamp(10px,1.2vw,16px);justify-content:flex-end}
@media (max-width:860px){.map--column{aspect-ratio:16/9}}
/* The address and the hours in that column are `.visit__lines`, which the
   showroom card and the Contact page's rows already are — the same facts set
   the same way, in the face those pages set them in. Only the spacing is this
   block's own, and it is scoped to this block: a bare `.visit__lines` rule
   here sits after theirs in the file and silently becomes theirs too. It did,
   on 23 September 2026, and it put the display serif through the Contact page
   and the showroom card until the screens came back. */
/* The words under a block's heading start the same distance below it wherever
   that pair appears. The enquiry's lede sat straight against its heading and
   the location's address did not, which read as two different blocks rather
   than two of the same — the project owner's word, 23 September 2026. One
   rule, both places, so they cannot drift apart again. */
#location .visit__lines,
#enquiry .brandtell__lede{margin-top:10px}
#location .visit__lines + .kicker{margin-top:clamp(18px,1.8vw,28px)}
/* The building is the line a visitor looks for, so it carries the weight and
   the three lines under it do not. 500 and not 700: the theme serves 300, 400
   and 500 of this face and nothing heavier, and a browser asked for a weight
   it has no file for draws a thickened fake — which on this face is the one
   thing that would look wrong. */
#location .visit__lines span:first-child{font-weight:500}

/* ============================================================
   The cookie notice
   ============================================================ */
/* A sheet across the foot of the window rather than a box over the middle of
   it. The middle is where a page puts something it will not let you past, and
   this is a question, not a gate: the reader may look at the page while they
   answer it, and on a page of legal text they may well want to.

   Its own dark ground, taken from the palette rather than from the section it
   lands on — it belongs to the site and not to the page under it, and it has to
   look the same arriving over a photograph as over paper. */
.consent{
  position:fixed;inset:auto 0 0 0;z-index:1200;
  color:#fff;
  /* The header's glass, not a wall: two grounds laid over one another — the
     palette's sheet and a white veil at the palette's own strength — over
     whatever the page has under it. The page stays visible through the notice,
     which is the difference between a question and a door. Written the same way
     as the menu panel because it is the same material, and a second recipe for
     one surface is two surfaces waiting to drift apart. */
  /* The header's second level, to the letter: the palette's sheet, the white
     veil at the palette's own strength, and the band's own veil over both. Not
     a lighter alpha invented here — that was the first attempt, and it made a
     fourth surface on a site that already has three. The lighter reading comes
     from the veil, the same way the brands band reads lighter than the menu it
     sits in without either of them being more transparent than the other. */
  /* Its own ground, and a light one: .44 against the menu's .85. The menu is a
     sheet you read a list on and can afford to be dense; this is a strip over a
     page somebody is still reading, and it should read as glass laid on that
     page rather than as a shelf in front of it.

     The band's white veil goes with it. A veil lightens the sheet, which is how
     the menu's second level reads lighter than the first — but on a ground this
     thin it lightens the ground the white type stands on, and there is nothing
     left to spend. What lifts it now is the blur: at 30px whatever is behind
     stops being anything a letter competes with, which is what pays for the
     alpha. One number, `--consent-ground`, if it wants to go further either
     way. */
  --consent-ground:rgba(16,13,10,.64);
  transition:background .35s ease;
  background:linear-gradient(rgba(255,255,255,var(--menu-lift)),rgba(255,255,255,var(--menu-lift))),var(--consent-ground);
  -webkit-backdrop-filter:blur(30px) saturate(1.15);backdrop-filter:blur(30px) saturate(1.15);
  /* The band's own edge value, not the panel's. It was .14 — the number the
     menu uses where it meets the page below it — and a rule four hundredths
     brighter reads as a different surface before the surface itself does. */
  border-top:1px solid var(--line);
  /* The token roles are restated, so the buttons inside read the dark set the
     way they do in a dark section rather than the page's own. */
  --fg:#FFFFFF;--fg-dim:rgba(255,255,255,.68);--line:rgba(255,255,255,.2);
  /* The accent carried further towards white than the page's. Brass was drawn
     to sit on a photograph the header dims; this sheet is darker than that, and
     at the palette's own value the label on it was a colour you had to look for
     rather than read. */
  --accent:color-mix(in srgb,var(--brass-lift) 62%,#fff);--accent-fg:var(--night);
  /* A lit switch is a filled shape and not a word, so it keeps the palette's own
     blue rather than the lifted one the type needs: a fill has the whole of
     itself to be read by, and the pale accent on a control this small looked
     like a second grey. */
  --consent-on:var(--brass-lift);
  /* Two veils, because they do different work. The panel's separates a second
     level from the first, and has to be seen across a wide band of glass; the
     switch's is the unlit half of a control and has to stay quieter than the
     lit half beside it. One value doing both made the panel too faint to read
     as a level of its own. */
  --consent-panel:rgba(255,255,255,.16);
  --consent-veil:rgba(255,255,255,.14);
  max-height:82dvh;overflow-y:auto;overscroll-behavior:contain;
}
/* While the preferences are open the page underneath is frozen rather than
   replaced: it keeps its scroll position and stops answering the drag, so the
   only thing that moves is the panel. The menu says the same thing about
   itself, and for the same reason — on a phone the panel is most of the screen
   and a finger on it was scrolling the page behind instead of reaching the
   buttons at the end of it. Stated on both elements because either one can be
   the scrolling box, depending on the browser. */
html.is-consent-open,html.is-consent-open body{overflow:hidden;overscroll-behavior:none}
.consent.is-open{max-height:92dvh}
/* On a phone the open panel takes the screen. A strip that grows upward until
   it is most of the window leaves the masthead stranded above it — a fixed row
   with `REQUEST AUDITION` in it, over a page that is frozen and cannot be got
   to, which reads as a header belonging to the panel rather than to the page
   behind it. Full height instead, and the sheet starts where it should: with
   the words that say what is being asked. */
@media (max-width:700px){
  .consent.is-open{inset:0;max-height:100dvh}
}
/* Over a page too light to carry white type through the glass — the packshot
   slide on its white sweep, or a document page — the sheet thickens until it
   does. The sixth slide answers the same problem by turning its caption over
   into ink on light, and that was tried here: on a strip this shallow the
   inversion reads as a second bar belonging to a different site, where a
   denser sheet still reads as the same notice with more of it.

   The reading behind it is the hero's: sample what is there, solve for what
   shows through the glass, and compare against the level at which white 12px
   type still reaches 4.5:1. Only the ground moves, because every other colour
   in the notice is a role token and none of them has to. */
.consent.is-dense{--consent-ground:rgba(16,13,10,.88);--consent-panel:rgba(255,255,255,.12)}
.consent__inner{
  /* Three pixels off each end of what a section would take. The bar is not a
     section: it is a line of type over somebody's reading, and the air a page
     gives a block of content reads as slack around a single sentence. */
  max-width:1240px;margin-inline:auto;padding:clamp(11px,1.3vw,17px) var(--edge);
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  /* Across only. The categories are a second row of this grid, and a row of no
     height still has a gap above it — which was putting a whole column gap
     under the sentence and making the bar look bottom-heavy while its padding
     was even. The space the categories need when they open is on their own
     inner box, where it belongs and where it opens with them. */
  column-gap:clamp(14px,1.8vw,26px);row-gap:0;align-items:center;
}
@media (max-width:860px){
  /* Stacked, the two are rows of one column and the gap has work to do again. */
  .consent__inner{grid-template-columns:minmax(0,1fr);row-gap:14px}
}
/* The notice is a bar, not a card. Its name and its sentence stand on one line
   where there is room for them, which takes two lines out of the height of a
   thing that sits over the page a reader is trying to read. */
.consent__say{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px clamp(14px,1.6vw,24px)}
.consent__title{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.22em;
  /* Stated, so the gap above the label is the padding and not the padding plus
     a line's leading — which is what made the top and the bottom of the bar
     look like two different measures when they were the same number. */
  text-transform:uppercase;color:var(--accent);flex:0 0 auto;line-height:1;
}
/* The last line's leading is taken back off the bottom. A line box is taller
   than its letters, so a paragraph sitting on the padding leaves the padding
   plus half a line under it, and the bar reads as heavier at the foot than at
   the head while both are the same number. .3em is exactly that half. */
.consent__say p{
  color:var(--fg-dim);font-size:14px;line-height:1.6;flex:1 1 100%;
  margin-bottom:-.3em;
}
/* The two policies belong to the panel where a reader is deciding, not to the
   line that asks the question. They are in the footer of every page as well, so
   nothing is out of reach while the notice is shut — and the notice is a
   sentence and three answers, which is as much as it should be. */
.consent__links{flex:1 1 100%;font-size:13px}
.consent:not(.is-open) .consent__links{display:none}
.consent__links a{color:var(--fg);border-bottom:1px solid var(--line)}
.consent__links a:hover{border-bottom-color:var(--fg)}
.consent__links span{margin-inline:8px;color:var(--fg-dim)}

/* Refusing is drawn as heavily as accepting. Where consent is asked for it has
   to be as easy to refuse as to give, and a refusal set as a faint link beside
   a filled button is a refusal the design is arguing against. The filled one is
   the last in the row because that is where a row of buttons is finished, not
   because it is the answer we would prefer. */
/* Tighter than a button elsewhere on the site. The row has to leave the
   sentence beside it enough width to break into two lines rather than three,
   and the padding is the only part of a button that is not its word. */
.consent__do{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.consent .button{padding:13px 18px}
/* One view at a time. What the notice says stays — a panel of switches with no
   heading and no policy links is a panel that has forgotten what it is asking
   about — and what goes is the paragraph and the three answers, because the
   categories now carry two of them and are the answer to the third. */
.consent.is-open .consent__do--notice{display:none}
.consent.is-open .consent__say p:not(.consent__links){display:none}
.consent.is-open .consent__say{gap:8px}
@media (max-width:860px){.consent__do .button{flex:1 1 auto}}

/* The categories, under the row and inside the same sheet — the menu's second
   level, built the same way. Closed until they are asked for: three answers are
   enough for most readers, and the fourth is for the one who wants to choose
   line by line.

   The outer box is a clip with no height and the ground is on the inner one, so
   nothing of it is drawn while it is shut. What travels is the clip and not the
   content.

   It travels to the height the categories actually are, the way the policy
   accordion travels — same duration, same curve, so the two openings on the
   site are one movement and not two. A ceiling stood in for that height before,
   and a ceiling has to be a number the content never reaches: at 240vh over a
   panel of 60vh the categories were fully out in the first eighth of the curve
   and the remaining seven eighths were spent on a clip nobody could see, which
   is an opening that reads as a jump and a closing that reads as a stall.
   `interpolate-size` is already asked for at the root for the accordion, and it
   is what lets a height of nothing travel to a height of `auto`. Where a
   browser does not have it the panel opens at once, as it did. */
.consent__cats{
  grid-column:1/-1;
  overflow:hidden;height:0;
  transition:height .72s cubic-bezier(.22,.35,.03,1);
}
.consent.is-open .consent__cats{height:auto}
@media (prefers-reduced-motion:reduce){.consent__cats{transition:none}}
/* A white veil over the sheet rather than a second, paler sheet: how much of
   the page stays visible through this is a palette decision already taken, and
   mixing towards white would have moved it. */
.consent__cats-inner{
  background:var(--consent-panel);
  border-top:1px solid var(--line);
  margin-top:clamp(14px,1.8vw,22px);
  padding:clamp(18px,2vw,26px) clamp(18px,2vw,26px) clamp(20px,2.2vw,28px);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:clamp(16px,2vw,28px) clamp(20px,3vw,48px);
}
.consent__cat{min-width:0}
/* The switch sits on the first line of the name, not in the middle of the whole
   label. Centred, a name that runs to two lines — or carries `always on` under
   it — pushed its switch down, and a column of switches that each sit at a
   different height is a column with no line in it. */
.consent__switch{display:flex;align-items:flex-start;gap:12px;cursor:pointer}
.consent__switch input{position:absolute;opacity:0;width:0;height:0}
/* Drawn rather than native, because a native checkbox is the one control on the
   page that would arrive in the browser's colours instead of the palette's. The
   focus ring is the page's own and is put back by hand, since the input it
   would have been drawn around is not the thing anybody sees. */
.consent__track{
  /* 18px on a 20px line, so it is centred on that line by a pixel either side. */
  flex:0 0 auto;width:34px;height:18px;border-radius:9px;margin-top:1px;
  background:var(--consent-veil);border:1px solid var(--line);
  position:relative;transition:background .2s,border-color .2s;
}
.consent__track::after{
  content:"";position:absolute;top:2px;left:2px;width:12px;height:12px;
  /* White in both states. The knob is the moving part and has to be the
     brightest thing in the control at either end of its travel; taking the
     accent's own foreground made it near-black, which read as a hole. */
  border-radius:50%;background:#fff;transition:transform .2s;
}
/* Lit, it keeps the same grey edge it has when it is off. An accent border on
   an accent fill leaves the control with no outline at all, and a row where the
   switched-on ones have lost their shape reads as a row of different objects. */
.consent__switch input:checked + .consent__track{
  background:var(--consent-on);border-color:var(--line);
}
.consent__switch input:checked + .consent__track::after{transform:translateX(16px)}
.consent__switch input:disabled + .consent__track{opacity:.5}
.consent__switch input:disabled ~ .consent__name{cursor:default}
.consent__switch input:focus-visible + .consent__track{outline:2px solid var(--accent);outline-offset:3px}
.consent__name{
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.12em;
  /* Stated rather than inherited: the switch beside it is positioned against
     this number, and a line height that comes from the page would move it. */
  line-height:20px;text-transform:uppercase;color:var(--fg);
}
.consent__always{
  display:block;margin-top:3px;font-size:10px;letter-spacing:.16em;
  color:var(--fg-dim);
}
.consent__note{
  margin-top:8px;font-size:13px;line-height:1.5;
  color:var(--fg-dim);padding-left:46px;
}
/* The row is pushed to the end of the panel so that `accept` sits under the
   last category rather than beside the first, and reads as the end of a
   decision instead of a shortcut past it. */
.consent__do--save{grid-column:1/-1;margin-top:4px;justify-content:flex-end}
@media (max-width:860px){.consent__do--save{justify-content:stretch}}

/* ============================================================
   Events — its own ground, the bar of years, the paging under a
   list, and the two things an event's page has that a legal page
   does not
   ============================================================ */
/* The middle of the section stands on a dark grey rather than on the palette's
   night, at the project owner's word of 23 September 2026. Written as the night
   itself and not as a background: `--night` is the token every dark block reads
   through `.section--dark`, so setting it here re-grounds every event row and
   anything added later, in one line and with no block knowing it happened. It
   is what the tokens section means by a dark section redefining a token and
   nothing else.

   Grey and not warm. The palette's night is a near-black carrying the brand's
   warmth, and asked for a grey that is plainly not black there is nothing to
   carry: a warm dark grey reads as brown at this lightness, which is the one
   thing it must not read as.

   **The head is outside it**, and that is the whole of the rule rather than an
   omission from it. The title stands on the blurred photograph the legal pages
   put it on, as it did before the grey and as it does on every other page of
   this site; what changed is the ground the reading stands on, which is the
   middle. So the exception is written into the selector rather than into a
   second rule that undoes the first — asked for on 23 September 2026, the
   evening the grey was first laid over both. */
.pagemain--events .section--dark:not(.pagehead){--night:#232323}

/* The picture on an index row stands on a plane, as the figures in a column on
   the About and Services pages do and as the panel on every feature band does.
   Two things are taken from the band rather than from the column figure: the
   weight, because this one lands on a flat dark ground rather than on white and
   a plane at the column figure's strength would read as a second picture; and
   the mirroring, because these rows alternate sides and a plane must be thrown
   outwards on both — away from the words, so the halves lean apart instead of
   into each other.

   Down and out, never up: a plane thrown up from a picture in a grid cell
   leaves the cell. The room it needs is taken out of the picture rather than
   added around it, so the row keeps its height and the photograph is a little
   smaller — the column figure's own trade.

   `--travel` and `--open` are both zero here, which is the finished
   composition; `site.js` writes them while the plane crosses and then undoes
   them, so with no script and no scroll the row is already right. */
.eventfigure{
  --plane:clamp(22px,2.6vw,40px);--open:0;
  --cut:calc(var(--plane) + (100% - var(--plane)) * var(--open));
  isolation:isolate;
  padding:0 var(--plane) var(--plane) 0;
  /* Until it has arrived the plane stands past the figure's edge, which on a
     narrow window is past the page's edge too — and a page wider than the
     window scrolls sideways. The figure clips what crosses its box; at rest
     the plane is inside it, so nothing of the settled row is lost. */
  overflow:clip;
}
.eventfigure::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  background:rgba(255,255,255,.2);
  transform:translate3d(var(--travel,0px),0,0);
  /* down and to the right, the bottom strip and the right strip left showing */
  inset:var(--plane) 0 0 var(--plane);
  clip-path:polygon(100% 0,calc(100% - var(--cut)) 0,
    calc(100% - var(--cut)) calc(100% - var(--cut)),0 calc(100% - var(--cut)),
    0 100%,100% 100%);
}
/* The row whose picture sits on the left throws its plane the other way. */
.service--flip .eventfigure{padding:0 0 var(--plane) var(--plane)}
.service--flip .eventfigure::before{
  inset:var(--plane) var(--plane) 0 0;
  clip-path:polygon(0 0,var(--cut) 0,
    var(--cut) calc(100% - var(--cut)),100% calc(100% - var(--cut)),
    100% 100%,0 100%);
}
/* The picture keeps its focus point inside the plane's padding. */
.eventfigure img{object-position:var(--focus,center)}

/* The two facts a reader came for — when, and which room — in the accent, and
   the rest of the block in the reading ink. The dates already stand in the
   accent on the index row's kicker, so this is the page agreeing with the row
   rather than a new colour: the site marks the thing you look up, and the
   accent is what it marks it with. The client's own name before the room stays
   in the ink, because it is not the fact being looked up. */
.eventfacts__key{color:var(--accent)}
.visit__lines .eventfacts__key{color:var(--accent)}
/* The strip the year bar stands on. A section's own rhythm is the distance
   between two things that are about different things; the bar is about the
   list under it, so it takes a row's height and a rule at the foot instead,
   and the head above it and the first event below it stay a section apart. */
.yearstrip{padding-block:clamp(14px,1.8vw,22px);border-bottom:1px solid var(--line)}
.yearbar ul{
  list-style:none;margin:0;padding:0;
  /* Wrapping rather than scrolling sideways. A row that scrolls needs
     something to say so, and every honest way of saying it costs more room
     than the years themselves: at 360px a tenth year would be off the edge
     with nothing to suggest it is there. Two lines of years hide nothing. */
  display:flex;flex-wrap:wrap;align-items:baseline;
  gap:4px clamp(14px,2vw,28px);
}
.yearbar a{
  display:block;padding-block:6px;
  font-family:var(--ui);font-size:12.5px;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;color:var(--fg-dim);text-decoration:none;
  border-bottom:1px solid transparent;
  transition:color .2s,border-color .2s;
}
.yearbar a:hover{color:var(--fg)}
/* The year being read, in the accent and on its own rule. It is still a link
   and still leads where it says: a reader who presses it lands where they
   already are, which is what every other current item on this site does. */
.yearbar a[aria-current]{color:var(--accent);border-bottom-color:var(--accent)}

/* The word before the dates on an event that has not happened yet. In the
   page's ink against the accent the dates are set in, so the two read as two
   facts rather than one long label, with the site's own separator between
   them. Computed from the dates and never typed — see `render_event_index()`. */
.kicker__now{color:var(--fg)}
.kicker__now::after{content:"·";margin-inline:.55em;color:var(--fg-dim)}

/* The paging under a list. The count on the left in the label face, the arrows
   on the right — the site's arrows, doing here what they do in the head of a
   legal page. There is no row of numbers: choosing is what the year bar above
   is for, and this only says there is more and which way it lies. */
.pager{display:flex;align-items:center;justify-content:space-between;gap:16px}
/* The band it stands on is a row, not a section. A full rhythm above and below
   one line of label leaves a white slab between the last event and the footer
   that reads as a missing block rather than as the end of a list. */
.pagerband{padding-block:clamp(22px,2.6vw,34px)}
/* The arrows are drawn for a photograph — a dark chip that darkens further —
   and this is the one place they stand on paper, where that chip reads as a
   grey box somebody forgot to style. On white they take the page's own ink on
   the page's own hairline, which is the language the ghost button beside them
   is already written in. */
.pager .arrowbtn{
  background:transparent;color:var(--fg);
  border:1px solid var(--line);
  transition:border-color .2s,color .2s;
}
.pager .arrowbtn:hover{background:transparent;border-color:var(--accent);color:var(--accent)}
.pager__count{
  margin:0;font-family:var(--ui);font-size:12.5px;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--fg-dim);
}
@media (max-width:700px){
  /* The arrows come off a photograph at this width because the picture can be
     dragged instead. Nothing can be dragged here — this is the only way to the
     rest of the list — so they stay, the way the legal pages' own arrows would
     if the swipe had not replaced them. */
  .pager .arrows{display:flex}
}

/* An event's paragraphs are read from the top to the end, like a legal page's,
   but they are not clauses and do not take the two-column setting. The reading
   measure, then, and nothing else — without it they would run the whole 1240px
   of the wrap. */
.prose--reading{max-width:var(--measure)}
/* Both edges, at the project owner's word of 23 September 2026, as the legal
   pages' clauses and the brand pages' prose are already set. Justified text
   needs hyphenation or it makes its own holes between the words.

   No `lang` on the box, unlike the brand page's maker block. That one carries
   `lang="en"` because its prose is English on a storefront that may be Russian;
   this copy goes through the theme's own catalogue and is translated with the
   page, so the language the browser should break the words by is the document's
   — and the document declares it in `header.php`. Hard-coding English here
   would be a promise this block cannot keep.

   The facts and the sign-off are left alone: a block of short lines has no
   second edge to reach, and a single sentence is one last line, which no
   justification touches. */
.eventbody__text p{text-align:justify;hyphens:auto}

/* The reading and the facts beside it.
   Below the desktop step the three boxes are simply three boxes in the order
   the markup puts them, which is the client's own: his paragraphs, his closing
   block, his sign-off. From 1081 up there is a margin to the right of the
   reading measure that would otherwise be the width of the column again in
   white, so the facts move into it and stand level with the first paragraph —
   which is also where a reader looking for the room would rather find them
   than five paragraphs down. The same seam the head's own rules are written
   against, so the page changes shape once and not twice. */
@media (min-width:1081px){
  .eventbody{
    display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);
    column-gap:clamp(40px,5vw,96px);align-items:start;
  }
  .eventbody__text{grid-column:1;grid-row:1}
  .eventbody > .eventfacts{grid-column:2;grid-row:1;margin-top:0}
  .eventbody > .eventclose{grid-column:1;grid-row:2}
}

/* The client's own closing block — the name, the dates, the place and the room
   — set apart from his paragraphs by a rule above and below rather than by a
   heading. It is the one part of the page a reader comes back to rather than
   reads, and a heading over four short lines would be a fifth line saying what
   the four already say. */
.eventfacts{
  margin-top:clamp(28px,3vw,44px);
  padding-block:clamp(18px,2vw,26px);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.eventfacts__lines{display:grid;gap:2px;margin:0;color:var(--fg-dim)}
/* The event's name is the line a reader looks for first, so it carries the
   weight and the three under it do not — the Contact page's rule for the same
   shape. 500 and not 700: the theme serves nothing heavier, and a browser asked
   for a weight it has no file for draws a thickened fake. */
/* The direct child, not any first span in the block. The room sits in a span of
   its own inside its line — it is the half of that line drawn in the accent —
   and it is the first element in it, so a bare `span:first-child` claimed it
   too and out-weighed the accent. 23 September 2026, the hour the accent was
   added. */
.eventfacts__lines > span:first-child{font-weight:500;color:var(--fg)}
/* His last line, in the face the rest of his page is read in. It was set in the
   display serif for an hour on 23 September 2026 and came off at the project
   owner's word: it is the last sentence of his letter, not a pull quote, and
   changing the face makes it something the site is saying about his words
   rather than his words. What sets it apart is the room above it and nothing
   else — it sits outside the reading box, so the ink is restated here rather
   than inherited from `.prose`. */
.eventclose{margin-top:clamp(20px,2.4vw,30px);color:var(--fg)}
/* The way back to the list. The arrows in the head lead to the next event and
   the one before it; neither of them is the section, and a reader who has
   finished should not have to reach for the menu. */
.eventback{margin-top:clamp(36px,4vw,64px)}
