/* Ported from tasarim/anasayfa.html. Embedded fonts and the hero image
   were extracted to assets/fonts and assets/img; everything else is verbatim. */


/* ---------------------------------------------------------------
   WordPress chrome reset.
   Core injects `margin-block-start:24px` on flow-layout children and on
   the top-level blocks. Those rules are written with :where(), so they
   are written as `:root :where(...)`, i.e. specificity 0,1,0. Repeating
   the exact same selectors here — and only here, at the top of the file
   — ties that specificity and wins on order, while every prototype rule
   further down (also 0,1,0, but later) still overrides this reset. Do
   NOT raise the specificity: a stronger selector would flatten the
   prototype's own margins too.
   --------------------------------------------------------------- */
:where(.wp-site-blocks) > *,
:root :where(.is-layout-flow) > *,
:root :where(.is-layout-constrained) > * { margin-block-start: 0; margin-block-end: 0; }
.wp-block-template-part { display: contents; }

@font-face{font-family:"Eurostile LT Pro";src:url("../fonts/EurostileLTPro-Regular.otf") format("opentype");font-weight:400;font-style:normal;font-display:swap;}
@font-face{font-family:"Eurostile LT Pro";src:url("../fonts/EurostileLTPro-Demi.otf") format("opentype");font-weight:600;font-style:normal;font-display:swap;}
@font-face{font-family:"Eurostile LT Pro";src:url("../fonts/EurostileLTPro-Bold.otf") format("opentype");font-weight:700;font-style:normal;font-display:swap;}

/* ============================================================
   EUROSTILE LT PRO — licensed cut, embedded.
   Demi = the medium half of the wordmark, Bold = the loud half.
   ============================================================ */

/* ============================================================
   BLACKRAM AUDIO — design tokens
   Committed single visual world (dark). Every colour painted
   explicitly so the page holds on any host ground.

   Display face: Michroma — the closest open substitute for
   Eurostile LT Extended. Swap in the licensed Eurostile via
   @font-face when the web licence is in hand.
   ============================================================ */
:root{
  --void:      #0A0908;
  --pitch:     #0E0D0B;
  --surface:   #141311;
  --surface-2: #1B1917;
  --iron:      #26241F;
  --iron-lit:  #3A362E;
  --smoke:     #8C877E;
  --bone:      #E8E2D6;
  --chalk:     #FAF8F4;
  /* The only colour on the site. Reserved for a refusal — a failed add, a
     product that cannot be bought — so it never competes with the design. */
  --alarm:     #B4564F;

  /* ---- author-settable: BLACKRAM → Colours ----
     Semantic tokens, each defaulting to the palette value the design shipped
     with. The settings screen redefines nothing else. Every rule that paints
     a price, a sale flag or a notice reads one of these, which is what makes
     a single change land everywhere the same thing appears — the price on a
     card and the price on its product page cannot drift apart.

     Borders and secondary text inside those components are derived from the
     text colour rather than set separately, so a light notice on a dark site
     (or the reverse) still holds together. */
  --br-price:     var(--chalk);
  --br-sale-bg:   rgba(10,9,8,.72);
  --br-sale-fg:   var(--bone);
  --br-notice-bg: var(--surface);
  --br-notice-fg: var(--chalk);

  --display: "Eurostile LT Pro", "Eurostile", "Bank Gothic", Impact, sans-serif;
  --body:    "Instrument Sans", "Helvetica Neue", Arial, sans-serif;
  --mono:    "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --rail: 84px;
  --maxw: 1440px;

  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  background:var(--void);
  color:var(--chalk);
  font-family:var(--body);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  /* the add-to-cart strip pushes the page down rather than covering it; the
     variable is written by cart-badge.js and is 0 the rest of the time */
  padding-top:var(--br-notice-h,0px);
  transition:padding-top .28s cubic-bezier(.22,.61,.36,1);
}
@media (prefers-reduced-motion:reduce){body{transition:none}}

body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:var(--grain);
  opacity:.035;mix-blend-mode:screen;
}

img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}

:focus-visible{outline:2px solid var(--bone);outline-offset:3px}

/* ---------- type roles ---------- */
.br-label{
  font-family:var(--mono);
  font-size:.6875rem;font-weight:400;
  letter-spacing:.22em;text-transform:uppercase;
  color:var(--smoke);
  display:flex;align-items:center;gap:.75rem;margin:0;
}
.br-label::before{content:"";width:22px;height:1px;background:var(--iron-lit);flex:none}

.br-h-display{
  font-family:var(--display);
  font-weight:400;
  text-transform:uppercase;
  letter-spacing:.075em;
  line-height:1.06;
  color:var(--chalk);
  margin:0;
}

.br-h-section{
  font-family:var(--display);
  font-weight:600;text-transform:uppercase;
  letter-spacing:.13em;
  font-size:clamp(1.1rem,2.1vw,1.7rem);
  line-height:1.2;margin:.75rem 0 0;color:var(--chalk);
}

.br-meta{
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.08em;
  color:var(--smoke);font-variant-numeric:tabular-nums;
}

.br-prose{color:var(--smoke);max-width:44ch;margin:0}

.br-wrap{
  width:100%;max-width:var(--maxw);
  margin-inline:auto;padding-inline:var(--gutter);
  position:relative;z-index:1;
}

/* ============================================================
   HEADER
   ============================================================ */
.br-site-head{
  position:fixed;inset:0 0 auto 0;z-index:50;
  border-bottom:1px solid transparent;
  transition:background-color .35s ease,border-color .35s ease,backdrop-filter .35s ease;
}
.br-site-head.is-stuck{
  background:rgba(10,9,8,.84);
  backdrop-filter:blur(14px);
  border-bottom-color:var(--iron);
}
.br-head-in{display:flex;align-items:center;justify-content:space-between;gap:clamp(1rem,2.2vw,2rem);height:78px}
/* The band between the menu breakpoint and a comfortable desktop — a small
   laptop, a half-width window, or any screen at 175–200% zoom. Everything in
   the bar is measured against the same wordmark, so that is what steps down;
   the labels keep their size, because they are the thing being read. */
@media (min-width:901px) and (max-width:1180px){
  .br-brand-word b,
  .br-brand-word span{font-size:.92rem;letter-spacing:.2em;margin-right:-.2em}
}

/* ---------- wordmark ----------
   BLACKRAM reads as the bold half, AUDIO as the medium half.
   Michroma ships one weight, so the hierarchy is built from
   scale, tracking and value instead of weight. ---------- */
.br-brand{display:inline-flex;align-items:baseline;gap:.34em}
.br-brand-word{display:inline-flex;align-items:baseline;gap:.34em;line-height:1}
.br-brand-word b{
  font-family:var(--display);font-weight:600;
  font-size:1.05rem;letter-spacing:.19em;
  text-transform:uppercase;color:var(--chalk);
  /* tracking trails the last glyph too; clawing it back keeps the
     gap between the two words exactly what the flex gap says */
  margin-right:-.19em;
  transition:color .25s ease;
}
.br-brand-word span{
  font-family:var(--display);font-weight:400;
  font-size:1.05rem;letter-spacing:.19em;
  text-transform:uppercase;color:var(--smoke);
  margin-right:-.19em;
  transition:color .25s ease;
}
.br-brand:hover .br-brand-word span{color:var(--chalk)}

/* The gap is fluid, not fixed. A browser at 200% zoom is a 960px viewport as
   far as CSS is concerned — above the 900px breakpoint, so the desktop row is
   still what renders, and at a fixed 1.9rem it did not fit: the labels wrapped
   mid-word, "SAMPLE PA / CKS" over two lines on the header's baseline. The gap
   now closes as the room does, which is what a row of labels should do before
   anything else gives. The same applies to a narrow laptop window, not just to
   zoom — zoom is only where it showed first. */
.br-nav{display:flex;gap:clamp(.8rem,1.6vw,1.9rem);align-self:stretch;align-items:center}
/* And a label is never broken across lines. If the row still runs out of room
   the whole thing scrolls, which is recoverable; a word split down the middle
   is not. */
.br-nav a{white-space:nowrap}
.br-nav a{
  font-family:var(--mono);font-size:.6875rem;
  letter-spacing:.18em;text-transform:uppercase;
  color:var(--smoke);padding:.5rem 0;position:relative;
  transition:color .2s ease;
}
.br-nav a::after{
  content:"";position:absolute;left:0;right:100%;bottom:0;height:1px;
  background:var(--bone);transition:right .28s cubic-bezier(.4,0,.2,1);
}
.br-nav a:hover{color:var(--chalk)}
.br-nav a:hover::after,.br-nav a[aria-current="page"]::after{right:0}
.br-nav a[aria-current="page"]{color:var(--chalk)}

/* ---------- header submenus ----------
   The parent stays a link and the chevron beside it is the disclosure, so a
   touch on the label goes to the category and a touch on the chevron opens
   the panel. `is-open` is set by script for pointer and click; :focus-within
   is the same thing for a keyboard with no script running. ---------- */
/* the group is stretched to the full header height so `top:100%` on its panel
   is the header's own bottom edge — no magic offset to keep in step with the
   78px bar */
.br-nav-item{position:relative;align-self:stretch;display:flex;align-items:center}
.br-nav-row{display:flex;align-items:center;gap:.28rem}
.br-sub-toggle{
  background:none;border:0;padding:.5rem 0;cursor:pointer;
  color:var(--smoke);display:grid;place-items:center;
  transition:color .2s ease,transform .24s ease;
}
.br-sub-toggle svg{width:13px;height:13px}
.br-nav-item:hover .br-sub-toggle,
.br-nav-item.is-open .br-sub-toggle{color:var(--chalk)}
.br-nav-item.is-open .br-sub-toggle{transform:rotate(180deg)}

.br-sub{
  position:absolute;top:calc(100% + 1px);left:-1rem;z-index:60;
  min-width:13rem;display:flex;flex-direction:column;
  padding:.5rem 0;
  background:rgba(10,9,8,.96);
  backdrop-filter:blur(14px);
  border:1px solid var(--iron);
  opacity:0;visibility:hidden;pointer-events:none;
  transform:translateY(-6px);
  transition:opacity .2s ease,transform .24s cubic-bezier(.22,.61,.36,1),visibility 0s linear .24s;
}
.br-nav-item.is-open > .br-sub,
.br-nav-item:focus-within > .br-sub{
  opacity:1;visibility:visible;pointer-events:auto;transform:none;
  transition:opacity .2s ease,transform .24s cubic-bezier(.22,.61,.36,1),visibility 0s;
}
/* Escape returns focus to the disclosure, which is inside the group — so
   `:focus-within` would immediately re-open what was just dismissed. This wins
   on source order at equal specificity; the script drops it again the moment
   focus leaves the group or the reader asks for the panel back. */
.br-nav-item.is-shut > .br-sub{opacity:0;visibility:hidden;pointer-events:none}
.br-sub a{padding:.55rem 1rem;letter-spacing:.14em}
.br-sub a::after{left:1rem;right:calc(100% - 1rem);bottom:.35rem}
.br-sub a:hover::after,.br-sub a[aria-current="page"]::after{right:1rem}
/* the nav dims its other labels while one is hovered; an open panel is not
   "one of the others" and must not fade with them */
.br-nav:hover .br-nav-item.is-open a,
.br-nav:hover .br-nav-item:focus-within a{opacity:1}
@media (prefers-reduced-motion:reduce){
  .br-sub{transition:none}
  .br-sub-toggle{transition:color .2s ease}
}

.br-head-tools{display:flex;align-items:center;gap:1.4rem}

/* ---------- header search ----------
   A <details>: the browser owns the open state, so the field is reachable with
   no script at all. Open, it is the whole screen — see search_panel() in
   chrome-blocks.php for why a strip under the header was not enough.

   The panel is `position:fixed`, and that is only true as long as no ancestor
   creates a containing block for it. `.br-site-head.is-stuck` carries a
   backdrop-filter, which does exactly that — so while the search is open the
   header drops its own blur and background. It has nothing to blur anyway: the
   overlay is already between it and the page. */
.br-search{position:static}
.br-search-toggle{list-style:none;display:grid;place-items:center}
.br-search-toggle::-webkit-details-marker{display:none}
.br-search-toggle::marker{content:""}
.br-search[open] .br-search-toggle{color:var(--chalk)}
/* the magnifier becomes the cross, so the control that opened it closes it —
   and it does so with no script, which is why there is no separate close
   button in the sheet */
.br-search .br-icon-close{display:none}
.br-search[open] .br-icon-open{display:none}
.br-search[open] .br-icon-close{display:block}

.br-search-panel{
  position:fixed;inset:var(--br-chrome-top,0) 0 0 0;z-index:60;
  display:grid;align-content:center;
  /* the same dynamic-viewport reason as the menu panel below */
  padding-bottom:env(safe-area-inset-bottom, 0px);
  background:color-mix(in srgb, var(--void) 76%, transparent);
  backdrop-filter:blur(20px) saturate(.55);
  animation:br-veil-in .3s cubic-bezier(.4,0,.2,1) both;
}
/* Said twice on purpose. `:has()` is the version that works with no script at
   all; the body class is the version that works in a browser without `:has()`.
   Either one alone leaves a case where the header keeps its backdrop-filter,
   and that filter is what would trap the fixed panel inside the 78px bar. */
body:has(.br-search[open]) .br-site-head,
body.br-search-open .br-site-head{
  z-index:80;background:transparent;backdrop-filter:none;border-bottom-color:transparent;
  /* Instantly, not over the .35s the stuck header normally takes. Scrolled
     down, the header is carrying its own plate and its own blur; letting those
     fade out on their own clock meant that for a third of a second the top
     78px of the veil was a different colour and a different blur from the rest
     of it — the overlay looked like it opened cut off across the top and then
     healed. Nothing here is worth animating: the veil arriving is the
     animation, and the header's plate has no job once it is behind one. */
  transition:none;
}
/* And the same on the way out, for one frame. Measured on the close, scrolled:
   the veil fades over 200ms with the header still bare, then — the instant the
   overlay's state comes off — the header starts its own .35s ramp from nothing,
   blur(0.3px) at 200ms, blur(6px) at 280ms, blur(14px) only at 560ms. For that
   third of a second the top 78px is a transparent strip over live copy that
   then fogs over on its own clock, which is the "two blurs fighting" the veil
   was supposed to have ended. `br-search-settling` is held by nav.js across a
   single frame so the plate is simply back, in the frame the veil left. */
body.br-search-settling .br-site-head{transition:none}
/* Two things stay above the veil, and raising the header cannot do it for them:
   the panel is a descendant of the header, so it is inside the same stacking
   context as the wordmark and the controls, and out-paints all of them. Each
   one that has to stay legible says so itself.

   The wordmark, so the screen still reads as this site rather than as a page
   that navigated somewhere. And the toggle, because it is now the cross — the
   only way out with no script running, so it cannot be under the blur. The
   account and cart go under it with everything else: while the search is open
   they are not what is being asked. */
body:has(.br-search[open]) .br-brand,
body.br-search-open .br-brand{position:relative;z-index:70}
.br-search[open] .br-search-toggle{position:relative;z-index:70}
/* The sheet arrives a beat after the veil, which is what makes the two read as
   one movement rather than a box appearing on a background. */
.br-search-sheet{
  display:flex;flex-direction:column;gap:1.1rem;width:100%;
  animation:br-sheet-in .38s cubic-bezier(.16,1,.3,1) .04s both;
}
/* A <details> stops rendering its panel the moment the attribute goes, so there
   is no exit to animate — unless something holds the attribute for the length
   of one. The script does; with no script the panel simply disappears, which is
   what it did before. */
.br-search.is-closing .br-search-panel{animation:br-veil-out .2s ease both}
.br-search.is-closing .br-search-sheet{animation:br-sheet-out .18s ease both}

@supports (height:100dvh){
  .br-search-panel{bottom:auto;height:calc(100dvh - var(--br-chrome-top, 0px))}
}

@keyframes br-veil-in{from{opacity:0}to{opacity:1}}
@keyframes br-veil-out{from{opacity:1}to{opacity:0}}
@keyframes br-sheet-in{
  from{opacity:0;transform:translateY(1.4rem) scale(.985)}
  to{opacity:1;transform:none}
}
@keyframes br-sheet-out{from{opacity:1}to{opacity:0;transform:translateY(.5rem)}}

/* The field is the largest type on the screen while it is open: it is the only
   thing the reader is being asked to do. */
.br-search-in{display:flex;align-items:center;gap:1rem}
.br-search-hint{
  margin:0;font-family:var(--mono);font-size:.625rem;
  letter-spacing:.18em;text-transform:uppercase;color:var(--smoke);
}
.br-search-panel .br-search-field{
  font-size:clamp(1.15rem,3.2vw,1.9rem);padding:.55rem 0;
}
.br-search-panel .br-search-field::placeholder{
  font-size:clamp(.7rem,1.4vw,.875rem);
}
.br-search-field{
  flex:1 1 auto;min-width:0;
  background:none;border:0;border-bottom:1px solid var(--iron-lit);
  padding:.65rem 0;border-radius:0;
  font-family:var(--body);font-size:1rem;color:var(--chalk);
  transition:border-color .2s ease;
}
.br-search-field::placeholder{
  color:var(--smoke);
  font-family:var(--mono);font-size:.75rem;letter-spacing:.16em;text-transform:uppercase;
}
.br-search-field:focus{outline:0;border-bottom-color:var(--bone)}
.br-search-go{
  flex:none;background:none;border:1px solid var(--iron-lit);cursor:pointer;
  padding:.6rem 1.4rem;color:var(--chalk);
  font-family:var(--mono);font-size:.625rem;letter-spacing:.18em;text-transform:uppercase;
  transition:border-color .2s ease,background-color .2s ease,color .2s ease;
}
.br-search-go:hover{background:var(--bone);border-color:var(--bone);color:var(--void)}
@media (max-width:560px){
  .br-search-in{gap:.6rem}
  .br-search-go{padding:.6rem .9rem;letter-spacing:.12em}
}
/* The page behind the veil must not scroll under the finger. Set by script; the
   panel itself has nothing to scroll, so there is nothing to restore. */
body.br-search-open{overflow:hidden}
/* Someone who asked the system for less movement gets the same screen without
   the entrance. The veil is the information, not the animation. */
@media (prefers-reduced-motion: reduce){
  .br-search-panel,
  .br-search-sheet,
  .br-search.is-closing .br-search-panel,
  .br-search.is-closing .br-search-sheet{animation:none}
}
.br-icon-btn{
  background:none;border:0;padding:.35rem;cursor:pointer;
  color:var(--smoke);display:grid;place-items:center;position:relative;
  transition:color .2s ease;
}
.br-icon-btn:hover{color:var(--chalk)}
.br-icon-btn svg{width:19px;height:19px}
/* Add-to-cart feedback on a product card: the icon is the whole control, so
   the confirmation has to happen inside it. */
.br-icon-btn[data-product-id]{transition:color .2s ease,transform .2s ease}
.br-icon-btn[data-product-id]:disabled{cursor:progress;opacity:.55}
.br-icon-btn[data-product-id].is-added{color:var(--bone);transform:scale(1.12)}
.br-icon-btn[data-product-id].is-added svg{display:none}
.br-icon-btn[data-product-id].is-added::after{
  content:"";width:15px;height:9px;
  border-left:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(-45deg) translate(1px,-2px);
}
.br-icon-btn[data-product-id].is-failed{color:var(--alarm)}

/* The note that follows an add-to-cart. It is a strip directly under the fixed
   header rather than a card floating over the page: the old one hung off the
   cart icon and spent four seconds sitting on top of whatever was in the top
   right corner — on /shop/ that was the sorting control. This one takes its
   own band. `--br-notice-h` on body opens the gap; the strip fills it, so
   nothing is ever covered. */
.br-notice-bar{
  position:fixed;left:0;right:0;top:var(--br-notice-top,0px);z-index:49;
  background:var(--br-notice-bg);
  border-bottom:1px solid var(--iron-lit);
  border-bottom-color:color-mix(in srgb, var(--br-notice-fg) 26%, transparent);
  /* it fades in place rather than sliding out from under the header: at the
     top of the home page that header is transparent, and anything sliding
     behind it is simply seen sliding */
  opacity:0;transform:translateY(-6px);
  visibility:hidden;pointer-events:none;
  transition:opacity .24s ease,transform .28s cubic-bezier(.22,.61,.36,1),visibility 0s linear .3s;
}
.br-notice-bar.is-in{
  opacity:1;transform:none;visibility:visible;pointer-events:auto;
  transition:opacity .24s ease,transform .28s cubic-bezier(.22,.61,.36,1),visibility 0s;
}
.br-notice-bar.is-error{border-bottom-color:#5a2b28}
.br-notice-in{
  display:flex;align-items:center;gap:1rem;
  min-height:46px;padding-block:.5rem;
}
/* Label, name, link and dismiss all come off one colour at different
   strengths. Pick a pale notice background in the settings and the whole row
   inverts with it instead of half of it staying dark on dark. */
.br-notice-label{
  flex:none;
  font-family:var(--mono);font-size:.5625rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--br-notice-fg);opacity:.6;
}
.br-notice-bar.is-error .br-notice-label{color:var(--alarm)}
/* the product name takes the slack and is the only part allowed to be cut */
.br-notice-name{
  flex:1 1 auto;min-width:0;
  font-family:var(--body);font-size:.8125rem;color:var(--br-notice-fg);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.br-notice-link{
  flex:none;
  font-family:var(--mono);font-size:.625rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--br-notice-fg);
  border-bottom:1px solid var(--iron-lit);
  border-bottom-color:color-mix(in srgb, var(--br-notice-fg) 40%, transparent);
  transition:border-color .2s ease;
}
.br-notice-link:hover{border-bottom-color:var(--br-notice-fg)}
.br-notice-close{
  flex:none;width:26px;height:26px;padding:0;
  background:none;border:0;cursor:pointer;
  color:var(--br-notice-fg);opacity:.6;
  display:grid;place-items:center;
  transition:opacity .2s ease;
}
.br-notice-close:hover{opacity:1}
.br-notice-close svg{width:11px;height:11px}
@media (max-width:560px){
  /* three items and a gutter do not fit; the name is what a phone can lose,
     since the strip is answering a tap the reader just made on that product.
     With it gone the link has to take over pushing the row apart. */
  .br-notice-name{display:none}
  .br-notice-link{margin-left:auto}
}
@media (prefers-reduced-motion:reduce){
  .br-notice-bar{transition:none}
}
.br-cart-count{
  position:absolute;top:-2px;right:-6px;min-width:16px;height:16px;padding:0 4px;
  border-radius:8px;background:var(--bone);color:var(--void);
  font-family:var(--mono);font-size:.5625rem;font-weight:500;
  display:grid;place-items:center;font-variant-numeric:tabular-nums;
}

/* ============================================================
   LEFT RAIL — real position, not decorative counters
   ============================================================ */
.br-rail{
  position:fixed;left:0;top:0;bottom:0;width:var(--rail);z-index:40;
  display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3.5rem;pointer-events:none;
}
.br-rail>*{pointer-events:auto}
.br-rail-index{display:flex;flex-direction:column;gap:1.15rem;align-items:center}
.br-rail-index a{
  display:flex;align-items:center;gap:.7rem;writing-mode:vertical-rl;
  font-family:var(--mono);font-size:.5625rem;
  letter-spacing:.28em;text-transform:uppercase;
  color:var(--iron-lit);transition:color .25s ease;
}
.br-rail-index a::before{content:"";width:1px;height:14px;background:currentColor;transition:height .25s ease}
.br-rail-index a:hover{color:var(--smoke)}
.br-rail-index a.is-active{color:var(--chalk)}
.br-rail-index a.is-active::before{height:30px}

.br-rail-social{display:flex;flex-direction:column;gap:1.15rem}
.br-rail-social a{color:var(--iron-lit);transition:color .2s ease}
.br-rail-social a:hover{color:var(--chalk)}
.br-rail-social svg{width:16px;height:16px}

/* ============================================================
   BUTTONS
   ============================================================ */
.br-btn{
  display:inline-flex;align-items:center;gap:.8rem;
  font-family:var(--mono);font-size:.6875rem;
  letter-spacing:.2em;text-transform:uppercase;
  padding:1rem 1.6rem;border:1px solid transparent;cursor:pointer;
  /* no gap in this list any more. The hover used to widen the gap, which
     widened the button, which shoved whatever stood next to it sideways -
     the arrow now travels inside the button instead. */
  transition:background-color .25s ease,color .25s ease,border-color .25s ease;
}
.br-btn svg{width:14px;height:14px;flex:none}
.br-btn-solid{background:var(--bone);color:var(--void);border-color:var(--bone)}
.br-btn-solid:hover,.br-btn-solid:focus-visible{background:var(--chalk);border-color:var(--chalk)}

/* the arrow leaves through the right and comes back in from the left,
   inside its own width: the gesture reads as forward motion and the
   button keeps every pixel of its box. It fades out before it reaches
   the padding, so nothing has to be clipped to hide it. */
@keyframes arrow-flow{
  0%   {transform:translateX(0);opacity:1}
  40%  {transform:translateX(170%);opacity:0}
  41%  {transform:translateX(-110%);opacity:0}
  62%  {transform:translateX(-55%);opacity:.3}
  100% {transform:translateX(0);opacity:1}
}
.br-btn-solid:hover svg,
.br-btn-solid:focus-visible svg,
.br-link-more:hover svg,
.br-link-more:focus-visible svg{animation:arrow-flow .58s cubic-bezier(.4,0,.2,1)}
.br-btn-ghost{
  background:rgba(10,9,8,.4);color:var(--smoke);border-color:var(--iron-lit);
  /* the flood that arrives under the label is motion-layer item 10.
     The label has to let it land first, hence the delay on colour -
     without it the text goes dark over a background that is still. */
  transition:color .3s ease .1s,border-color .3s ease,
             background-color .25s ease;
}
.br-btn-ghost:hover,.br-btn-ghost:focus-visible{color:var(--void);border-color:var(--bone)}

/* ============================================================
   HERO — the photograph is the thesis
   ============================================================ */
.br-hero{position:relative;min-height:100svh;display:flex;align-items:center}

.br-hero-media{position:absolute;inset:0;z-index:0;overflow:hidden;background:var(--void)}
.br-hero-fog{position:absolute;inset:0;width:100%;height:100%;z-index:0;display:block}
/* the photograph sits on true black; screen-blending it over the page
   ground makes those pixels vanish instead of forming a visible edge */
/* The cutout carries its own composition — the animal is baked into the
   right of a 1920x1072 frame with the left 45% transparent — so the old
   translateX hack and the screen blend that hid its seam are both gone.
   contain, not cover: cover scales to height on anything narrower than
   1.79:1 and clips the right horn. The letterbox contain leaves is
   transparent, so it costs nothing here. Anchored right so the extra
   width on wide screens goes to the empty side, not the animal. */
/* Sized in rem, not off the viewport, and this is the whole of item 11.
   Browser zoom works by changing how many CSS pixels the window holds: at 50%
   the viewport reports twice the width, so anything measured in % of it draws
   at the same physical size while every rem-sized thing on the page halves.
   The animal was 100% of a full-viewport box, so it sat unmoved at 1440
   physical pixels wide at any zoom while the headline shrank beside it.
   The cap is exactly what the box renders at the 1440px design width
   (1440x804), so nothing moves there; past it the picture holds its size and
   zoom finally has an effect on it. */
.br-hero-media img{
  position:absolute;top:50%;right:0;z-index:3;
  transform:translateY(-50%);
  width:min(100%, 90rem);
  height:min(100%, 50.25rem);
  object-fit:contain;object-position:right center;
}
.br-hero-stamps{position:absolute;inset:0;z-index:3;pointer-events:none}
.br-hero-stamps span{
  position:absolute;font-family:var(--mono);font-size:.5625rem;
  letter-spacing:.26em;text-transform:uppercase;color:var(--iron-lit);
  line-height:2;text-align:right;
}
.br-hero-stamps .br-s-top{top:6.5rem;right:var(--gutter)}
.br-hero-stamps .br-s-bot{bottom:3rem;right:var(--gutter)}
/* Sits under the cutout now, so the effects behind the animal are the
   only thing it darkens. The bottom dissolve moved out to .br-hero-fade,
   which has to sit *over* the animal — its body runs off the frame. */
.br-hero-scrim{
  position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(90deg,
      rgba(10,9,8,.95) 0%,
      rgba(10,9,8,.80) 30%,
      rgba(10,9,8,.24) 46%,
      rgba(10,9,8,0)   58%,
      rgba(10,9,8,.22) 100%),
    linear-gradient(180deg,
      rgba(10,9,8,.92) 0%,
      rgba(10,9,8,.20) 24%,
      rgba(10,9,8,.20) 100%);
}
.br-hero-fade{
  position:absolute;inset:0;z-index:4;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(10,9,8,0)   52%,
    rgba(10,9,8,.35) 76%,
    rgba(10,9,8,.86) 92%,
    var(--void)      100%);
}

.br-hero-grid{
  display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  align-items:center;width:100%;padding-block:9rem 5rem;
}
/* Centred: for a hero with no photograph beside the copy. The second column
   only exists to keep the wording out of the picture, so with no picture it is
   dropped rather than left as dead space the copy is still squeezed against. */
.br-hero-grid.is-centered{grid-template-columns:minmax(0,1fr);justify-items:center}
.br-hero-grid.is-centered .br-hero-copy{align-items:center;text-align:center;max-width:60ch}
.br-hero-grid.is-centered .br-hero-actions{justify-content:center}
/* The eyebrow's rule reads as a margin mark on the left of a column; centred,
   one rule on one side is a lopsided object, so it gets its pair. */
.br-hero-grid.is-centered .br-label{justify-content:center}
.br-hero-grid.is-centered .br-label::after{
  content:"";width:22px;height:1px;background:var(--iron-lit);flex:none;
}
/* ---- the scroll cue ----
   Sits above .br-hero-fade (z-index 4) and the stamps (5), because it is the
   one thing down there meant to be read. A link, not a decoration: it goes to
   the first section, and `scroll-padding-top` on <html> keeps that section
   clear of the fixed header. */
.br-hero-cue{
  position:absolute;left:50%;bottom:2.25rem;z-index:6;
  transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:.65rem;
  color:var(--smoke);
  font-family:var(--mono);font-size:.5625rem;letter-spacing:.26em;
  text-transform:uppercase;line-height:1;
  transition:color .25s ease;
}
.br-hero-cue:hover,.br-hero-cue:focus-visible{color:var(--chalk)}
.br-hero-cue-mouse{
  display:block;position:relative;
  width:21px;height:33px;border:1px solid currentColor;border-radius:11px;
}
.br-hero-cue-mouse i{
  position:absolute;left:50%;top:6px;
  width:2px;height:6px;border-radius:1px;background:currentColor;
  transform:translateX(-50%);
  animation:br-cue 2.1s cubic-bezier(.4,0,.2,1) infinite;
}
/* The wheel is visible for most of the cycle rather than a quarter of it: a
   mark that is blank more often than not reads as a rendering fault. */
@keyframes br-cue{
  0%   {opacity:0;transform:translate(-50%,0)}
  14%  {opacity:1;transform:translate(-50%,1px)}
  56%  {opacity:1;transform:translate(-50%,11px)}
  78%  {opacity:0;transform:translate(-50%,14px)}
  100% {opacity:0;transform:translate(-50%,14px)}
}
/* The wheel stops but the mark stays: the cue is an affordance, not entry
   choreography, so switching motion off must not delete the only thing on the
   first screen that says there is a second one. */
body.br-still .br-hero-cue-mouse i{animation:none;opacity:1}
@media (prefers-reduced-motion:reduce){
  .br-hero-cue-mouse i{animation:none;opacity:1}
}

.br-hero-copy{display:flex;flex-direction:column;align-items:flex-start;gap:1.85rem}
.br-hero-title{font-size:clamp(2.15rem,5.5vw,4.85rem)}
.br-hero-title span{display:block}
.br-hero-actions{display:flex;flex-wrap:wrap;gap:.9rem}

/* ============================================================
   SECTIONS
   ============================================================ */
.br-section{padding-block:clamp(4.5rem,9vw,8rem);position:relative;z-index:1}
.br-section-head{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:2rem;flex-wrap:wrap;margin-bottom:2.75rem;
}
.br-link-more{
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--smoke);
  display:inline-flex;align-items:center;gap:.6rem;
  transition:color .2s ease;
}
.br-link-more:hover{color:var(--chalk)}
.br-link-more svg{width:13px;height:13px}

.br-grid-packs{
  display:grid;
  gap:clamp(1rem,1.7vw,1.75rem);
  grid-template-columns:repeat(4,minmax(0,1fr));
}
.br-card{
  background:var(--surface);
  display:flex;flex-direction:column;position:relative;
  border:1px solid var(--iron);
  isolation:isolate;
  transition:background-color .3s ease,border-color .3s ease,box-shadow .45s ease,transform .35s ease;
  transform:perspective(900px) rotateX(0deg) rotateY(0deg);
}
.br-card:hover{
  background:var(--surface-2);
  border-color:var(--iron-lit);
  box-shadow:0 22px 60px -28px rgba(0,0,0,.9), 0 0 0 1px rgba(232,226,214,.07);
}

/* ---- a film of glass that catches the pointer ----
   Bone light, and only bone light. A prism used to sit under it: the
   one place colour entered this page, and on a two-value brand it read
   as somebody else's effect. The highlight is now the whole trick. */
.br-card::before,
.br-card::after{
  content:"";position:absolute;inset:0;z-index:3;
  pointer-events:none;opacity:0;
  transition:opacity .45s ease;
}
.br-card::before{
  background:
    radial-gradient(circle 300px at var(--mx,50%) var(--my,40%),
      rgba(232,226,214,.13), rgba(232,226,214,.035) 44%, transparent 70%);
  mix-blend-mode:screen;
}
.br-card::after{
  background:repeating-linear-gradient(to bottom,
    rgba(232,226,214,.04) 0 1px, transparent 1px 3px);
  mix-blend-mode:screen;
}
.br-card:hover::before,.br-card:focus-within::before{opacity:1}
.br-card:hover::after,.br-card:focus-within::after{opacity:1;animation:scan 5.5s linear infinite}
@keyframes scan{from{background-position-y:0}to{background-position-y:60px}}

/* the cover title blooms on hover. It used to split into blue and
   pink — chromatic aberration is a colour trick, and this palette
   has no colour to aberrate into. */
.br-card-art .br-art-word b{transition:text-shadow .35s ease}
.br-card:hover .br-art-word b{
  text-shadow:0 0 18px rgba(232,226,214,.42);
}

.br-card-art{position:relative;aspect-ratio:1/1;overflow:hidden;display:grid;place-items:center;background:var(--pitch)}
/* Sold out: said twice on purpose. The flag carries the words, for anyone who
   never reaches the button; the struck basket carries the same fact to a
   reader already going for the click. */
.br-card-flag{
  position:absolute;top:.8rem;left:.8rem;z-index:6;
  font-family:var(--mono);font-size:.5625rem;letter-spacing:.14em;text-transform:uppercase;
  padding:.32rem .5rem;color:var(--alarm);
  border:1px solid rgba(180,86,79,.45);background:rgba(10,9,8,.72);
}
.br-icon-btn-off{color:var(--alarm);cursor:not-allowed}
.br-icon-btn-off:hover{color:var(--alarm)}
.br-card-art canvas{position:absolute;inset:0;width:100%;height:100%}
/* a featured image stands in for the procedural cover, same box and parallax */
.br-card-art > img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.br-card-art .br-art-word{position:relative;text-align:center;padding:1rem}
.br-card-art .br-art-word b{
  display:block;font-family:var(--display);font-weight:600;
  font-size:clamp(.8rem,1.25vw,1.1rem);
  letter-spacing:.19em;text-transform:uppercase;color:var(--chalk);
}
.br-card-art .br-art-word span{
  display:block;margin-top:.65rem;
  font-family:var(--mono);font-size:.5625rem;
  letter-spacing:.26em;text-transform:uppercase;color:var(--smoke);
}

.br-preview{
  position:absolute;inset:auto 0 0 0;z-index:4;
  display:flex;align-items:center;gap:.65rem;padding:.75rem .9rem;
  background:linear-gradient(to top,rgba(10,9,8,.94),transparent);
  opacity:0;transform:translateY(6px);
  transition:opacity .28s ease,transform .28s ease;
}
.br-card:hover .br-preview,.br-card:focus-within .br-preview{opacity:1;transform:none}
.br-preview button{
  width:26px;height:26px;flex:none;border-radius:50%;
  border:1px solid var(--iron-lit);background:rgba(10,9,8,.6);
  color:var(--chalk);display:grid;place-items:center;cursor:pointer;
  transition:background-color .2s ease,border-color .2s ease,color .2s ease;
}
.br-preview button:hover{background:var(--bone);color:var(--void);border-color:var(--bone)}
.br-preview button svg{width:9px;height:9px}
/* No demo clip: the strip is artwork, and the canvas keeps the old treatment. */
.br-preview-mute .br-wave{flex:1;height:18px;opacity:.5}

/* ============================================================
   DEMO PLAYER
   The card strip and the wider player on a product page share
   every control, so everything here is written once and only
   the sizes differ. A playing card keeps its strip visible —
   otherwise the transport disappears the moment the pointer
   leaves, while the sound carries on.
   ============================================================ */
.br-card.is-playing .br-preview{opacity:1;transform:none}

.br-wave-wrap{
  position:relative;                 /* .br-card-art canvas is absolute; this
                                        is what keeps the waveform inside the
                                        strip instead of over the artwork */
  flex:1;min-width:0;height:18px;cursor:pointer;
  touch-action:none;                 /* dragging the playhead must not scroll */
}
.br-wave-wrap .br-wave{position:absolute;inset:0;display:block;width:100%;height:100%;opacity:1}
.br-wave-wrap:focus-visible{outline:2px solid var(--bone);outline-offset:2px}

[data-br-player] .br-play-off{display:none}
[data-br-player].is-playing .br-play-on{display:none}
[data-br-player].is-playing .br-play-off{display:block}
[data-br-player].is-broken .br-play{opacity:.4;cursor:not-allowed}

/* Sized for the longest thing it will ever say ("0:03 / 0:08") so the
   waveform does not shrink the moment playback starts. */
.br-time{
  flex:none;font-family:var(--mono);font-size:.5625rem;letter-spacing:.06em;
  color:var(--smoke);font-variant-numeric:tabular-nums;white-space:nowrap;
  min-width:5.6em;text-align:right;
}
/* A card shows one figure, so it needs room for four characters, not eleven. */
[data-compact] .br-time{min-width:3.2em}

.br-vol-wrap{display:flex;align-items:center;gap:.3rem;flex:none}
.br-preview .br-mute{
  width:22px;height:22px;border-color:transparent;background:none;color:var(--bone);
}
.br-preview .br-mute:hover{background:none;border-color:transparent;color:var(--chalk)}
.br-preview .br-mute svg{width:12px;height:12px}
[data-br-player] .br-vol-off{display:none}
[data-br-player].is-muted .br-vol-on{display:none}
[data-br-player].is-muted .br-vol-off{display:block}
[data-br-player].is-muted .br-mute{color:var(--smoke)}

/* The stock range control is a white bar with a fat thumb — the one bright
   object in a dark room. Drawn instead as the same hairline-and-dot the rest
   of the interface uses. */
.br-vol{
  -webkit-appearance:none;appearance:none;
  width:56px;height:14px;margin:0;padding:0;
  background:none;cursor:pointer;
}
.br-vol::-webkit-slider-runnable-track{height:2px;background:var(--iron-lit);border-radius:2px}
.br-vol::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;
  width:10px;height:10px;margin-top:-4px;border-radius:50%;background:var(--bone);
}
.br-vol::-moz-range-track{height:2px;background:var(--iron-lit);border-radius:2px}
.br-vol::-moz-range-thumb{width:10px;height:10px;border:0;border-radius:50%;background:var(--bone)}
.br-vol:focus-visible{outline:2px solid var(--bone);outline-offset:3px}
/* On a card the slider waits until the strip is actually being used: at rest
   the design is a play button and a waveform, which is what it always was. */
.br-vol-compact .br-vol{
  width:0;opacity:0;transition:width .22s ease,opacity .22s ease;
}
.br-vol-compact:hover .br-vol,
.br-vol-compact:focus-within .br-vol{width:48px;opacity:1}
/* A touch device has no hover to reveal it with, and its own volume keys. */
@media (hover:none){
  .br-vol-compact .br-vol{display:none}
}

/* ---- the wider player, under the cover on a product page ---- */
.br-demo{
  margin-top:1rem;padding:.85rem 1rem .95rem;
  border:1px solid var(--iron);background:var(--surface);
}
.br-demo-label{
  display:block;font-family:var(--mono);font-size:.5625rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--smoke);margin-bottom:.6rem;
}
.br-demo-row{display:flex;align-items:center;gap:.85rem}
.br-demo .br-play{
  width:38px;height:38px;flex:none;border-radius:50%;
  border:1px solid var(--iron-lit);background:var(--surface-2);
  color:var(--chalk);display:grid;place-items:center;cursor:pointer;
  transition:background-color .2s ease,border-color .2s ease,color .2s ease;
}
.br-demo .br-play:hover{background:var(--bone);color:var(--void);border-color:var(--bone)}
.br-demo .br-play svg{width:14px;height:14px}
.br-demo .br-wave-wrap{height:44px}
.br-demo .br-time{font-size:.625rem}
.br-demo .br-mute{
  width:26px;height:26px;flex:none;border:0;background:none;color:var(--bone);
  display:grid;place-items:center;cursor:pointer;
}
.br-demo .br-mute:hover{color:var(--chalk)}
.br-demo .br-mute svg{width:15px;height:15px}
@media (max-width:520px){
  .br-demo-row{gap:.6rem}
  .br-demo .br-vol{width:44px}
}

/* The body takes the slack so the price row can sit on the floor of the card
   whatever the title and the specs do above it. Both of those are clamped to
   two lines: a shop owner can type a paragraph into the spec override, and
   without the clamp that one product sets the height of the whole row. */
.br-card-body{padding:1.05rem 1.1rem 1.2rem;display:flex;flex-direction:column;gap:.55rem;border-top:1px solid var(--iron);flex:1 1 auto}
.br-card-title{
  font-family:var(--body);font-size:.9375rem;font-weight:500;color:var(--chalk);margin:0;
  line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.br-card-specs{
  font-family:var(--mono);font-size:.625rem;letter-spacing:.06em;
  color:var(--smoke);font-variant-numeric:tabular-nums;line-height:1.7;margin:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  /* the clamp hides the overflow but cannot break a single unspaced string,
     which is what an override pasted out of a spreadsheet often is */
  overflow-wrap:anywhere;
}
/* The spec lines belong to the price row, not to the title. Left in normal flow
   they followed the title down whenever it wrapped to a second line, so in a row
   of cards the same information sat at three different heights. The auto margin
   moves to the specs, and the foot then simply follows them: title at the top,
   specs and price on the floor, whatever the title does in between. */
.br-card-specs{margin-top:auto}
.br-card-foot{display:flex;align-items:center;justify-content:space-between;margin-top:auto;padding-top:.35rem}
.br-card-specs + .br-card-foot{margin-top:0}
.br-price{font-family:var(--mono);font-size:.875rem;font-weight:500;color:var(--br-price);font-variant-numeric:tabular-nums}
/* On sale WooCommerce hands us <del>old</del><ins>new</ins>. The old figure is
   demoted rather than dropped: it is the reason the new one reads as an offer. */
.br-price del{color:var(--smoke);font-size:.75rem;margin-right:.45rem;text-decoration:line-through}
.br-price ins{color:var(--br-price);text-decoration:none;background:none}

/* ============================================================
   PLUGIN BAND
   ============================================================ */
.br-plugin{background:var(--pitch);border-block:1px solid var(--iron)}
.br-plugin-grid{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:clamp(2rem,5vw,4.5rem);align-items:center}
.br-plugin-ui{border:1px solid var(--iron);background:var(--surface);aspect-ratio:16/10;position:relative;overflow:hidden}
/* A still stands in for the canvas in the same box, so the frame, the badge and
   the 16:10 ratio hold whichever one the block is set to. */
.br-plugin-ui canvas,
.br-plugin-ui img{position:absolute;inset:0;width:100%;height:100%}
.br-plugin-ui img{object-fit:cover;display:block}
.br-plugin-ui .br-ui-tag{
  position:absolute;top:.85rem;left:1rem;
  font-family:var(--mono);font-size:.5625rem;letter-spacing:.26em;
  text-transform:uppercase;color:var(--smoke);
}
.br-plugin-copy{display:flex;flex-direction:column;align-items:flex-start;gap:1.4rem}
.br-spec-list{display:grid;grid-template-columns:auto 1fr;gap:.55rem 1.6rem;width:100%;border-top:1px solid var(--iron);padding-top:1.2rem;margin:0}
.br-spec-list dt{font-family:var(--mono);font-size:.625rem;letter-spacing:.2em;text-transform:uppercase;color:var(--smoke)}
.br-spec-list dd{margin:0;font-family:var(--mono);font-size:.75rem;color:var(--chalk);font-variant-numeric:tabular-nums}

/* ============================================================
   VALUE STRIP
   ============================================================ */
.br-values{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border:1px solid var(--iron);background:var(--surface)}
.br-value{
  position:relative;overflow:hidden;
  padding:2.1rem 1.6rem;display:flex;gap:1.1rem;align-items:flex-start;
  border-left:1px solid var(--iron);
  transition:background-color .35s ease;
}
.br-value:first-child{border-left:0}
/* the same rule that wipes under a menu item, along the top of the cell.
   The strip had four static boxes; this is the cheapest way to make it
   answer the pointer without adding another colour or another shadow */
.br-value::before{
  content:"";position:absolute;left:0;right:100%;top:0;height:1px;
  background:var(--bone);
  transition:right .5s cubic-bezier(.4,0,.2,1);
}
.br-value:hover{background:var(--surface-2)}
.br-value:hover::before{right:0}
.br-value svg{
  width:26px;height:26px;flex:none;color:var(--bone);opacity:.74;
  transition:opacity .35s ease,transform .45s cubic-bezier(.22,.61,.36,1);
}
.br-value:hover svg{opacity:1;transform:translateY(-2px)}
/* the index reads as a spec sheet, which is the register the rest of
   the page is already in */
.br-value-no{
  position:absolute;top:1.15rem;right:1.15rem;
  font-family:var(--mono);font-size:.5625rem;letter-spacing:.22em;
  color:var(--iron-lit);font-variant-numeric:tabular-nums;
  transition:color .35s ease;
}
.br-value:hover .br-value-no{color:var(--smoke)}
.br-value h3{
  margin:0 0 .45rem;font-family:var(--mono);font-size:.6875rem;font-weight:500;
  letter-spacing:.2em;text-transform:uppercase;color:var(--chalk);
}
.br-value p{margin:0;font-size:.8125rem;line-height:1.6;color:var(--smoke)}

/* ============================================================
   CTA BAND - the last thing before the footer. One field, one
   button, and a floor that throws sparks. Nothing here is warm:
   the band has the shape of an ember and the value of bone.
   ============================================================ */
.br-cta{
  position:relative;overflow:hidden;
  background:var(--pitch);border-top:1px solid var(--iron);
  padding-block:clamp(3.5rem,7vw,6rem);
}
.br-cta-embers{position:absolute;inset:0;z-index:0;width:100%;height:100%;display:block;pointer-events:none}
.br-cta::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(115% 85% at 50% 116%,rgba(232,226,214,.10),transparent 62%);
}
.br-cta-in{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;gap:1.1rem;
}
/* .br-wrap owns the page margin and centres itself; a max-width on the
   wrap element would centre the whole band, so the measure goes on the
   children instead */
.br-cta-in > *{width:100%;max-width:56ch}
.br-cta-form{display:flex;gap:.6rem;flex-wrap:wrap;width:100%;margin-top:.5rem}
.br-cta-input{
  flex:1 1 15rem;min-width:0;
  background:rgba(10,9,8,.55);border:1px solid var(--iron-lit);color:var(--chalk);
  font-family:var(--mono);font-size:.8125rem;letter-spacing:.06em;
  padding:1rem 1.1rem;
  transition:border-color .25s ease,background-color .25s ease;
}
.br-cta-input::placeholder{
  color:var(--smoke);font-size:.6875rem;
  letter-spacing:.2em;text-transform:uppercase;
}
.br-cta-input:focus{border-color:var(--bone);background:rgba(10,9,8,.82)}
.br-cta-note{
  margin:.2rem 0 0;min-height:1.3em;
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--smoke);
}
.br-cta-note.is-ok{color:var(--chalk)}

/* ============================================================
   CONTACT FORM
   Longer than the mailing list strip, so it is laid out rather
   than lined up: label above field, name and address side by
   side while there is room. Field treatment is the CTA input's,
   because two different text fields on one site is one too many.
   ============================================================ */
.br-contact{max-width:44rem}
.br-contact-intro{color:var(--smoke);margin:0 0 1.8rem;max-width:56ch}
.br-field-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:0 1rem}
.br-field-wrap{display:flex;flex-direction:column;gap:.45rem;margin:0 0 1.15rem}
.br-field-wrap > label{
  font-family:var(--mono);font-size:.625rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--smoke);
}
.br-field{
  width:100%;box-sizing:border-box;
  background:rgba(10,9,8,.55);border:1px solid var(--iron-lit);color:var(--chalk);
  font-family:var(--mono);font-size:.8125rem;letter-spacing:.04em;
  padding:.85rem 1rem;
  transition:border-color .25s ease,background-color .25s ease;
}
.br-field:focus{border-color:var(--bone);background:rgba(10,9,8,.82)}
.br-field::placeholder{color:var(--smoke);font-size:.75rem}
textarea.br-field{resize:vertical;min-height:9.5rem;line-height:1.75}
select.br-field{
  appearance:none;-webkit-appearance:none;padding-right:2.6rem;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%238C877E' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1rem center;background-size:11px;
}
.br-contact .br-consent{margin:.5rem 0 1.5rem}
/* Cloudflare draws the challenge inside an iframe it owns, so the only things
   reachable from here are the box around it and the room it sits in. Width is
   left to the widget's own `flexible` size rather than forced: an iframe
   stretched past what Cloudflare laid out inside it just gains empty space. */
.br-turnstile{margin:0 0 1.5rem;max-width:19.5rem}
.br-turnstile iframe{display:block}
.br-contact-note{
  margin:1rem 0 0;min-height:1.3em;
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--smoke);
}
.br-contact-note.is-ok{color:var(--chalk)}
/* The one colour on the site is reserved for a refusal, and a form that will
   not send is exactly that. */
.br-contact-note.is-bad{color:var(--alarm)}

/* ============================================================
   FOOTER
   ============================================================ */
.br-site-foot{border-top:1px solid var(--iron);padding-top:clamp(3rem,6vw,4.5rem);padding-bottom:2rem;position:relative;z-index:1}
.br-foot-grid{display:grid;grid-template-columns:minmax(0,1.6fr) repeat(3,minmax(0,1fr));gap:clamp(2rem,4vw,3.5rem)}
.br-foot-brand{display:flex;flex-direction:column;gap:1.2rem;align-items:flex-start}
.br-foot-brand p{margin:0;font-size:.8125rem;color:var(--smoke);max-width:34ch}
.br-foot-social{display:flex;gap:1.1rem}
.br-foot-social a{color:var(--smoke);transition:color .2s ease}
.br-foot-social a:hover{color:var(--chalk)}
.br-foot-social svg{width:17px;height:17px}

.br-foot-col h4{margin:0 0 1.15rem;font-family:var(--mono);font-size:.625rem;font-weight:400;letter-spacing:.24em;text-transform:uppercase;color:var(--smoke)}
.br-foot-col ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.7rem}
.br-foot-col a{font-size:.8125rem;color:var(--chalk);opacity:.72;transition:opacity .2s ease}
.br-foot-col a:hover{opacity:1}
/* a footer column has room to simply show its sub-items: indented, one step
   quieter, no disclosure to find */
.br-foot-col .br-foot-sub{margin-top:.7rem;padding-left:.9rem;gap:.55rem;border-left:1px solid var(--iron)}
.br-foot-col .br-foot-sub a{font-size:.75rem;opacity:.55}
.br-foot-col .br-foot-sub a:hover{opacity:.9}

/* PARTICLE MARK - two instances: the hero tagline and the footer
   signature. The <span> is the real thing in both; the canvas over it
   is a second rendering of the same word. Size, tracking and alignment
   belong to the instance, and the script reads the alignment back off
   the computed style, so centring is a CSS decision only. */
.br-pmark{position:relative;line-height:.92}
.br-pmark-text{
  display:block;white-space:nowrap;
  font-family:var(--display);font-weight:600;
  text-transform:uppercase;color:var(--iron);
  transition:opacity .5s ease;
}
.br-pmark canvas{position:absolute;inset:0;width:100%;height:100%;display:block}

/* the line that opens everything under the hero. It sits in normal flow
   at the top of the first section, so the box is the content column and
   centring needs no arithmetic. The padding is not decoration: the
   canvas is the box, the points fly in from outside the letterforms and
   the pointer pushes them out again, and a line-height-tall box clips
   both. */
/* a section that opens with a mark carries less of its own top padding -
   the mark brings its own, and stacked they read as a hole */
.br-section.br-opens{padding-top:clamp(2.25rem,4.5vw,4rem)}
.br-open-mark{
  padding-block:clamp(2rem,5vh,3.6rem);
  margin-bottom:clamp(1.5rem,4vw,3rem);
  text-align:center;
}
.br-open-mark .br-pmark-text{
  font-size:clamp(1.1rem,3.6vw,2.8rem);
  letter-spacing:.2em;color:var(--iron-lit);
}
/* where the canvas never takes over, the type is the thing on screen and
   has to read as type, not as a watermark */
@media (max-width:900px){
  .br-open-mark{padding-block:clamp(1.2rem,4vh,2.4rem)}
  .br-open-mark .br-pmark-text{color:var(--smoke)}
}
@media (prefers-reduced-motion:reduce){
  .br-open-mark .br-pmark-text{color:var(--smoke)}
}

.br-foot-base{margin-top:clamp(2.5rem,5vw,4rem);padding-top:1.5rem;border-top:1px solid var(--iron);display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.br-foot-base p{margin:0}

/* Payment marks and the ETBIS certificate. The logos arrive in whatever
   colours their issuers mandate, which is the one place on this site colour is
   not ours to remove — so they are dimmed to sit in the page and lift to full
   strength on hover, rather than being recoloured. */
.br-foot-badges{margin-top:clamp(2.5rem,5vw,3.5rem);padding-top:1.5rem;border-top:1px solid var(--iron)}
.br-foot-badges-title{margin:0 0 1rem;color:var(--smoke)}
.br-foot-badges-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1.5rem 2rem}
.br-badge-marks{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem 1.1rem;margin:0;padding:0;list-style:none}
.br-badge-marks li{display:flex;align-items:center}
.br-badge-marks img{display:block;width:auto;height:26px;max-width:100%;opacity:.62;transition:opacity .25s ease}
.br-badge-marks li:hover img{opacity:1}
.br-badge-cert{display:inline-flex;align-items:center;gap:.7rem;text-decoration:none;color:var(--smoke)}
.br-badge-cert img{display:block;width:auto;height:52px;max-width:100%;opacity:.72;transition:opacity .25s ease}
.br-badge-cert:hover img{opacity:1}
.br-badge-cert span{font-size:.6875rem;letter-spacing:.08em;text-transform:uppercase;max-width:18ch;line-height:1.4}
a.br-badge-cert:hover span{color:var(--bone)}

@media (max-width:640px){
  .br-foot-badges-row{justify-content:flex-start}
  .br-badge-marks img{height:22px}
  .br-badge-cert img{height:44px}
}

.br-reveal{opacity:0;transform:translateY(18px);transition:opacity .7s ease,transform .7s ease}
.br-reveal.is-in{opacity:1;transform:none}
/* the strip arrives cell by cell; one block of four sliding up together
   reads as a single object, and these are four separate claims */
.br-value.br-reveal:nth-child(2){transition-delay:.09s}
.br-value.br-reveal:nth-child(3){transition-delay:.18s}
.br-value.br-reveal:nth-child(4){transition-delay:.27s}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:1180px){
  .br-rail{display:none}
  .br-grid-packs{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:1181px){
  .br-wrap{padding-left:calc(var(--rail) + var(--gutter))}
}
@media (max-width:900px){
  .br-nav{display:none}
  .br-hero{flex-direction:column;min-height:0}
  .br-hero-media{position:relative;inset:auto;width:100%;height:46vh;min-height:280px}
  .br-hero-media img{object-position:center center}
  .br-hero-stamps{display:none}
  .br-hero-scrim{
    background:linear-gradient(180deg,rgba(10,9,8,.72) 0%,rgba(10,9,8,.05) 34%,rgba(10,9,8,.55) 78%,var(--void) 100%);
  }
  .br-hero-grid{grid-template-columns:1fr;padding-block:2.5rem 4rem}
  .br-plugin-grid{grid-template-columns:1fr}
  .br-values{grid-template-columns:repeat(2,minmax(0,1fr))}
  .br-value:nth-child(3){border-left:0}
  .br-value:nth-child(n+3){border-top:1px solid var(--iron)}
  .br-foot-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .br-cta-in > *{max-width:none}
}
@media (max-width:560px){
  .br-grid-packs{grid-template-columns:1fr}
  .br-values{grid-template-columns:1fr}
  .br-value{border-left:0;border-top:1px solid var(--iron)}
  .br-value:first-child{border-top:0}
  .br-foot-grid{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
  .br-reveal{opacity:1;transform:none}
  .br-card{transform:none!important}
  .br-card:hover::after,.br-card:focus-within::after{animation:none}
}

/* ============================================================
   MOTION LAYER
   Ideas borrowed from React Bits / 21st.dev, written without
   React. Everything is opt-in through data-anim or an existing
   class, so the markup ports into PHP templates unchanged —
   the theme only has to enqueue this pair of files.

   Timing is deliberately not one token: entry decelerates
   (ease-out), pointer tracking is instant, returns are slower
   than departures. One duration for everything reads as canned.
   ============================================================ */

.br-sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ---- 1. split: the headline assembles out of focus, character
   by character. <i> rather than <span> so .br-hero-title span{display:block}
   keeps applying to the lines and not to the letters. ---- */
.br-hero-title i.br-ch{
  display:inline-block;font-style:normal;
  opacity:0;transform:translateY(.4em);filter:blur(10px);
}
.br-hero-title.is-split i.br-ch{
  transition:opacity .6s cubic-bezier(.22,.61,.36,1),
             transform .6s cubic-bezier(.22,.61,.36,1),
             filter .6s cubic-bezier(.22,.61,.36,1);
}
.br-hero-title.is-split i.br-ch.is-lit{opacity:1;transform:none;filter:none}

/* ---- 2. decrypt: the mono labels resolve out of noise. While the
   glyphs churn they sit at rail colour, so the noise reads as
   machinery rather than as text you failed to catch. ---- */
[data-anim="decrypt"] .br-dec{white-space:pre}
[data-anim="decrypt"] .br-dec.is-noise{color:var(--iron-lit)}

/* ---- 3. scroll reveal: the paragraph lights word by word, tied
   to scroll position rather than to a timer ---- */
[data-anim="words"] .br-wd{
  display:inline-block;
  opacity:.16;filter:blur(2.5px);
  transition:opacity .3s ease,filter .3s ease;
}
[data-anim="words"] .br-wd.is-lit{opacity:1;filter:none}

/* ---- 4. sheen: one pass of light across the solid button. The
   pseudo-element sits above the button's own background but under
   its text — isolation makes the negative z-index stop there. ---- */
.br-btn-solid{position:relative;overflow:hidden;isolation:isolate}
.br-btn-solid::before{
  content:"";position:absolute;inset:-1px;z-index:-1;
  background:linear-gradient(105deg,
    rgba(255,255,255,0) 38%,
    rgba(255,255,255,.85) 50%,
    rgba(255,255,255,0) 62%);
  transform:translateX(-140%);
}
@keyframes sheen{from{transform:translateX(-140%)}to{transform:translateX(140%)}}
.br-btn-solid:hover::before,
.br-btn-solid:focus-visible::before{animation:sheen .8s cubic-bezier(.4,0,.2,1)}

/* ---- 5. nav: the glyphs of the hovered label flip through noise and
   settle, left to right, while the rest of the row steps back. Same
   alphabet as the section labels, so the header and the page speak in
   one voice. The labels are set in DM Mono: a swapped glyph takes
   exactly the advance of the real one, so nothing in the row moves.
   The wordmark has to pin its width for the same trick, because the
   display face it is set in is not monospaced. ---- */
.br-nav a{transition:color .2s ease,opacity .3s ease}
.br-nav a .br-ns-row{display:inline-block}
.br-nav a .br-ns{display:inline-block;font-style:normal;white-space:pre}
.br-nav a .br-ns.is-noise{color:var(--smoke)}
.br-nav:hover a{opacity:.36}
.br-nav:hover a:hover,
.br-nav a:focus-visible{opacity:1}

/* ---- 6. wordmark: AUDIO re-scrambles on hover (the same engine the
   section labels use) and BLACKRAM draws its own rule. The rule stops
   .19em short because the tracking of the last glyph is clawed back
   with a negative margin above — right:0 would overshoot the R. ---- */
/* the scrambled glyphs are not the width of the real ones, and .br-head-in
   is a space-between row — the width is pinned in script so the churn
   stays inside the logo instead of walking the nav sideways */
.br-brand-word span{flex:none;white-space:nowrap}
.br-brand-word b{position:relative}
.br-brand-word b::after{
  content:"";position:absolute;left:0;right:100%;bottom:-.42em;height:1px;
  background:var(--bone);
  transition:right .38s cubic-bezier(.4,0,.2,1);
}
.br-brand:hover .br-brand-word b::after,
.br-brand:focus-visible .br-brand-word b::after{right:.19em}

/* ---- 7. cards: the tilt tracks the pointer with no transition at
   all — a transition on transform is what made the old one feel like
   it was arriving late. The return keeps its easing, slower than the
   departure. Inside the art window two layers move against each other,
   which is what actually sells the depth; the card itself can't use
   translateZ because isolation:isolate flattens preserve-3d. ---- */
.br-card{
  transition:background-color .3s ease,border-color .3s ease,
             box-shadow .45s ease,
             transform .55s cubic-bezier(.22,.61,.36,1);
}
.br-card.is-tilting{
  transition:background-color .3s ease,border-color .3s ease,box-shadow .45s ease;
}
.br-card:hover{
  box-shadow:0 24px 60px -28px rgba(0,0,0,.9), 0 0 0 1px rgba(232,226,214,.08);
}
/* direct child only — .br-preview .br-wave is also a canvas inside .br-card-art.
   Travel is roughly half what it was: the two layers still move against
   each other, which is what sells depth, but the card no longer looks
   like it is being handled. */
.br-card-art > :is(canvas,img){
  transform:scale(1.06)
            translate3d(calc(var(--px,0) * 6px), calc(var(--py,0) * 4px), 0);
}
.br-card-art .br-art-word{
  transform:translate3d(calc(var(--px,0) * -12px), calc(var(--py,0) * -8px), 0);
}
.br-card:not(.is-tilting) .br-card-art > :is(canvas,img),
.br-card:not(.is-tilting) .br-card-art .br-art-word{
  transition:transform .55s cubic-bezier(.22,.61,.36,1);
}
/* entry gets its own short easing: without it the card snaps to whatever
   angle the pointer happened to cross the border at */
.br-card.is-entering{
  transition:background-color .3s ease,border-color .3s ease,box-shadow .45s ease,
             transform .22s cubic-bezier(.22,.61,.36,1);
}
.br-card.is-entering .br-card-art > :is(canvas,img),
.br-card.is-entering .br-card-art .br-art-word{
  transition:transform .22s cubic-bezier(.22,.61,.36,1);
}
.br-card:hover .br-art-word b{
  text-shadow:0 0 20px rgba(232,226,214,.48);
}

/* ---- 8. hero lattice: a dot field that brightens and leans toward
   the cursor. It runs the full width now and the cutout
   occludes it, which is what the horizontal mask used to fake.
   Hidden below 900px, where the hero stacks and the media band is
   too short for a lattice to read as anything but noise. ---- */
.br-hero-dots{
  position:absolute;inset:0;z-index:2;
  width:100%;height:100%;display:block;pointer-events:none;
}
.br-hero-stamps{z-index:5}
@media (max-width:900px){.br-hero-dots{display:none}}

/* ---- 10. flow fill: the ghost buttons take a bone flood that grows
   out of the point where the pointer crossed the border, and drains
   back toward wherever it leaves. A circle scaled by transform rather
   than an animated width - the compositor can carry the first one. ---- */
.br-btn-ghost{position:relative;overflow:hidden;isolation:isolate}
.br-btn-ghost::before{
  content:"";position:absolute;z-index:-1;
  left:var(--fx,50%);top:var(--fy,50%);
  width:24px;height:24px;margin:-12px 0 0 -12px;
  border-radius:50%;background:var(--bone);
  transform:scale(0);
  transition:transform .5s cubic-bezier(.22,.61,.36,1);
}
.br-btn-ghost:hover::before,
.br-btn-ghost:focus-visible::before{transform:scale(var(--flow,20))}

/* ---- 11. CTA embers: sparks lift off the plate behind the mailing
   list. Bone, not orange - the band is an ember for the shape of the
   motion, not for a colour this palette does not own. ---- */
.br-cta-embers{opacity:.9}

/* ---- 12. footer wordmark: the word is sampled off an offscreen
   canvas and rebuilt out of points. The plain text under it stays in
   the document - it is what a screen reader reads, what a narrow
   screen shows, and what is left standing if none of this runs. ---- */
.br-pmark canvas{opacity:0;transition:opacity .6s ease}
.br-pmark.is-live canvas{opacity:1}
.br-pmark.is-live .br-pmark-text{opacity:0}

/* ---- 9. below the stacking breakpoint the page goes quiet. The animal
   is dropped rather than squeezed into a short band — at that width it
   reads as a sticker, not a photograph — and every effect starts
   finished. A phone gets the page, not the performance. ---- */
@media (max-width:900px){
  .br-hero-media{display:none}
  /* the header is fixed and the media band used to clear it */
  .br-hero-grid{padding-block:7.5rem 3.5rem}
  /* Without the photograph the opening screen is only as tall as its words,
     and 3.5rem of bottom padding is less than the cue is tall — measured, it
     sat 32px on top of the buttons. Only paid for when the cue is on. */
  .br-hero.has-cue .br-hero-grid{padding-bottom:7.5rem}
  .br-reveal{opacity:1;transform:none}
  .br-hero-title i.br-ch{opacity:1;transform:none;filter:none}
  [data-anim="words"] .br-wd{opacity:1;filter:none}
  .br-card{transform:none!important}
  .br-card-art > :is(canvas,img){transform:scale(1.06)}
  .br-card-art .br-art-word{transform:none}
  .br-btn-solid::before{display:none}
  /* no flood without a pointer - and with the flood gone the label has
     to go back to reading light-on-dark, or it turns invisible */
  .br-btn-ghost::before{display:none}
  .br-btn-ghost:hover,.br-btn-ghost:focus-visible{color:var(--chalk);border-color:var(--smoke)}
  .br-btn-solid:hover svg,.br-link-more:hover svg{animation:none}
}

/* ---- the site-wide switch (BLACKRAM → Motion) ----
   Same resting state the reduced-motion query asks for, reached from a
   setting instead of from the machine. Only the entry choreography is
   undone: every one of these rules exists because something starts hidden,
   blurred or displaced and waits for script to release it, and with the
   script standing down they would wait forever. Hover is left alone — it
   answers an action, it does not happen to the reader. */
body.br-still .br-reveal{opacity:1;transform:none}
body.br-still .br-card{transform:none}
body.br-still .br-hero-title i.br-ch{opacity:1;transform:none;filter:none}
body.br-still [data-anim="words"] .br-wd{opacity:1;filter:none}
body.br-still .br-card-art > :is(canvas,img){transform:scale(1.06)}
body.br-still .br-card-art .br-art-word{transform:none}

@media (prefers-reduced-motion:reduce){
  .br-hero-title i.br-ch{opacity:1;transform:none;filter:none}
  [data-anim="words"] .br-wd{opacity:1;filter:none}
  .br-card-art > :is(canvas,img){transform:scale(1.06)}
  .br-card-art .br-art-word{transform:none}
  .br-btn-solid:hover::before,.br-btn-solid:focus-visible::before{animation:none}
  .br-btn-solid:hover svg,.br-btn-solid:focus-visible svg,
  .br-link-more:hover svg,.br-link-more:focus-visible svg{animation:none}
  .br-btn-ghost::before{display:none}
  .br-btn-ghost:hover,.br-btn-ghost:focus-visible{color:var(--chalk);border-color:var(--smoke)}
}

/* ============================================================
   INNER PAGES
   The homepage opens with a 900px hero, so the fixed header has
   something to sit on. Every other template needs that height
   made up explicitly, plus the section rhythm the homepage gets
   from .br-section.
   ============================================================ */
.br-page{
  padding-block: calc(78px + clamp(2.5rem, 5vw, 4.5rem)) clamp(4rem, 8vw, 7rem);
  min-height: 60vh;
}
.br-page-head{
  display:flex;flex-wrap:wrap;justify-content:space-between;
  gap:1.5rem;margin-bottom:clamp(2rem,4vw,3.25rem);
  padding-bottom:1.25rem;border-bottom:1px solid var(--iron);
  /* The heading and the toolbar beside it have to read off ONE line, and the
     line the eye follows is the baseline, not the bottom of a box. Aligned on
     box bottoms the sorting control's text sat 9px above the heading's
     baseline, because a <select> is a bordered box with its own padding.
     `last baseline` so a heading that wraps aligns on its final line, with
     flex-end left standing as the fallback where it is not supported. */
  align-items:flex-end;
  align-items:last baseline;
}
.br-page-head h1,
.br-page-title{
  font-family:var(--display);font-weight:600;text-transform:uppercase;
  letter-spacing:.13em;font-size:clamp(1.25rem,2.6vw,2rem);
  line-height:1.2;margin:0;color:var(--chalk);
}
/* the toolbar used to be a wrapper group inside the head; it is now the
   `blackram/catalog-tools` block itself, styled in store.css */
.br-page .br-prose{max-width:64ch}
.br-page p{color:var(--smoke)}
/* Inner-page prose links. Two exclusions worth stating:
   - `.wp-element-button` is WordPress's own class for a link rendered as a
     button, and an underlined chalk link on a bone button is invisible.
   - `.br-checkout` (cart, checkout, account) is not prose: it is a dense pile
     of WooCommerce block links — product names, disclosures, quantity steppers
     — that must not all pick up an underline. `store.css` opts the handful of
     genuine prose links there back in, rather than out-specifying this rule
     component by component. */
/* The exclusions are all the same kind of thing: a link that is a component's
   own control rather than a word in a sentence. A card's title, a card's
   cover, a button. Underlining those says "this is prose you can follow",
   which is the one thing they are not. */
.br-page:not(.br-checkout) a:not(.br-btn):not(.wp-element-button):not(.br-card-title a):not(.br-post-title a):not(.br-post-cover){
  color:var(--chalk);border-bottom:1px solid var(--iron-lit);
}
.br-page:not(.br-checkout) a:not(.br-btn):not(.wp-element-button):not(.br-post-title a):not(.br-post-cover):hover{border-bottom-color:var(--bone)}
/* Headings in a flow of copy. A product card's title is an h3 too, but it is a
   component's own label, not prose — and this rule out-specifies the `margin:0`
   the card sets on it (0,1,1 against 0,1,0), so 2.5rem of air was opening above
   every title on the shop and the category archives. The front page escaped it
   only because its <main> carries no `br-page`. */
.br-page :is(h2,h3):not(.br-card-title):not(.br-post-title){
  font-family:var(--display);font-weight:600;text-transform:uppercase;
  letter-spacing:.1em;color:var(--chalk);margin:2.5rem 0 .75rem;
}

/* ---------- long-form page copy ----------
   The legal pages are the first real prose on the site: eight Turkish and six
   English documents of headings, tables and dense paragraphs. `contentSize` is
   1440px because the store grids want it, and a 1440px line of body text is
   unreadable, so the measure is set here rather than in theme.json.

   Scoped to `.br-longform`, a class carried by the post-content block of
   `templates/page.html` alone. A product description or a checkout column must
   not inherit any of it.

   Tables are the exception to the measure: a four-column cookie inventory does
   not fit in 74 characters, so tables run to the full wrapper and scroll
   sideways below it rather than being squeezed. */
.br-longform > *{max-width:74ch}
.br-longform > .wp-block-table{max-width:100%}
.br-longform p,
.br-longform li{line-height:1.75}
.br-longform p{margin:0 0 1.15rem}
.br-longform strong{color:var(--bone);font-weight:500}
.br-longform em{color:var(--bone);font-style:italic}
.br-longform .wp-block-list{color:var(--smoke);padding-left:1.15rem;margin:0 0 1.5rem}
.br-longform .wp-block-list li{margin-bottom:.55rem}
.br-longform .wp-block-list li::marker{color:var(--iron-lit)}
.br-longform code{
  font-family:var(--mono);font-size:.8125em;color:var(--bone);
  background:var(--surface);border:1px solid var(--iron);
  padding:.1em .35em;border-radius:2px;
}
.br-longform .wp-block-separator{
  border:0;border-top:1px solid var(--iron);
  margin:clamp(2rem,4vw,3rem) 0;height:0;
}
.br-longform .wp-block-table{margin:0 0 1.75rem;overflow-x:auto}
.br-longform table{
  width:100%;border-collapse:collapse;
  font-size:.875rem;line-height:1.55;
}
.br-longform th,
.br-longform td{
  border:1px solid var(--iron);padding:.65rem .8rem;
  text-align:left;vertical-align:top;color:var(--smoke);
}
.br-longform th{
  font-family:var(--mono);font-size:.6875rem;font-weight:400;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--chalk);background:var(--surface);
}
.br-longform td strong{color:var(--chalk);font-weight:400}

/* the link to the other language, set above the first heading. Quiet on
   purpose: it is a way out for the reader who landed on the wrong version,
   not a call to action. */
.br-lang-alt{
  font-family:var(--mono);font-size:.6875rem;letter-spacing:.12em;
  text-transform:uppercase;margin:0 0 2rem;
}

/* an archive or a search that found nothing */
.br-empty-note{
  font-family:var(--mono);font-size:.8125rem;letter-spacing:.06em;
  color:var(--smoke);margin:0;padding:3rem 0;
}
.br-empty-note strong{color:var(--chalk);font-weight:400}

/* paging under a product grid */
.br-pager{display:flex;gap:.35rem;justify-content:center;margin-top:3rem}
.br-pager .page-numbers{
  min-width:38px;height:38px;display:grid;place-items:center;padding:0 .6rem;
  border:1px solid var(--iron);color:var(--smoke);
  transition:border-color .2s ease,color .2s ease;
}
.br-pager .page-numbers:hover{border-color:var(--iron-lit);color:var(--chalk)}
.br-pager .page-numbers.current{border-color:var(--bone);color:var(--void);background:var(--bone)}

/* ============================================================
   JOURNAL
   The blog reuses the shop's card idea rather than inventing a
   second one: same plate, same border, same hover, a title
   clamped so a long one cannot set the height of its whole row.
   What differs is the cover ratio — an article's picture is
   landscape, a pack's cover is square — and that a post leads
   with its date rather than its price.
   ============================================================ */
/* Three across, not the shop's four: an article card carries a sentence of
   summary, and four columns of that is a column of two-word lines. Stated
   explicitly rather than with auto-fill, so a page holding three posts shows
   three cards across and not three cards and a hole. */
.br-post-grid{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(1.25rem,2.4vw,2rem);
}
@media (max-width:1180px){
  .br-post-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:640px){
  .br-post-grid{grid-template-columns:1fr}
}
.br-post-card{
  display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--iron);
  transition:border-color .3s ease,background-color .3s ease;
}
.br-post-card:hover,
.br-post-card:focus-within{border-color:var(--iron-lit);background:var(--surface-2)}

/* The cover is a link too, but a second link to the same place is a second
   stop for anyone tabbing through and a duplicate announcement for anyone
   listening — so it is taken out of both, and the title carries the visit. */
.br-post-cover{
  display:block;position:relative;aspect-ratio:16/10;overflow:hidden;
  background:var(--pitch);border-bottom:1px solid var(--iron);
}
.br-post-cover img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .7s cubic-bezier(.16,1,.3,1);
}
.br-post-card:hover .br-post-cover img{transform:scale(1.045)}
/* No featured image: the first word of the title, set large, rather than a grey
   rectangle. A list of articles with no art still reads as a designed list. */
.br-post-plate{
  position:absolute;inset:0;display:grid;place-items:center;padding:1rem;
  font-family:var(--display);font-size:clamp(1.1rem,3.4vw,1.6rem);
  letter-spacing:.18em;text-transform:uppercase;color:var(--iron-lit);
  text-align:center;overflow-wrap:anywhere;
}
.br-post-card:hover .br-post-plate{color:var(--smoke)}

.br-post-body{
  display:flex;flex-direction:column;gap:.6rem;flex:1 1 auto;
  padding:1.05rem 1.15rem 1.3rem;
}
.br-post-meta{
  margin:0;font-family:var(--mono);font-size:.625rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--smoke);
}
.br-post-title{
  margin:0;font-family:var(--body);font-size:1rem;font-weight:500;
  line-height:1.35;color:var(--chalk);letter-spacing:0;text-transform:none;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.br-post-title a{color:inherit;border-bottom:0}
.br-post-card:hover .br-post-title{color:var(--bone)}
/* The excerpt takes the slack, so every card in a row ends level whatever the
   titles above them did — the same arrangement the product cards use. */
.br-post-excerpt{
  margin:0 0 0;font-size:.8125rem;line-height:1.65;color:var(--smoke);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}

/* ---------- a single article ---------- */
.br-article .br-page-head{align-items:flex-start}
.br-post-byline{margin:0}
.br-article-cover{margin:0 0 clamp(2rem,4vw,3rem)}
.br-article-cover img{
  display:block;width:100%;height:auto;
  border:1px solid var(--iron);background:var(--pitch);
}
/* The categories under the article are a way out of it, not a caption. */
.br-article-terms{
  margin:clamp(2rem,4vw,3rem) 0 0;padding-top:1.25rem;
  border-top:1px solid var(--iron);color:var(--smoke);
}
.br-article-terms a{color:var(--chalk)}
.br-related{margin-top:clamp(3rem,6vw,4.5rem)}
.br-related > .br-h-section{margin:0 0 1.5rem}

@media (max-width:900px){
  .br-page{padding-block: calc(78px + 2rem) 3.5rem;}
}

/* An anchor jump puts the target's top edge at y=0, and 79px of it is then
   under the fixed header — measured on /#packs at both 1440 and 420. Nothing
   in the page had ever declared the offset. Everything the header can be
   pushed down by is in the sum: the admin bar, and the notice band that opens
   under it after an add-to-cart. */
html{
  scroll-padding-top: calc(78px + var(--br-chrome-top, 0px) + var(--br-notice-h, 0px) + 1.25rem);
}

/* honeypot: present for bots, gone for everyone else */
.br-hp{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
/* said to a screen reader, not drawn. Same geometry as the honeypot, kept as
   its own class because the two are removed for opposite reasons. */
.br-vh{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ============================================================
   MOBILE NAVIGATION
   The prototype hid .br-nav outright below 900px, which is fine
   for a one-page demo and useless for a shop. The same list is
   reused as a panel; the toggle is display:none on desktop so
   nothing above 900px moves by a pixel.
   ============================================================ */
.br-nav-toggle{display:none}

@media (max-width:900px){
  .br-nav-toggle{
    display:grid;place-items:center;order:3;
    background:none;border:0;padding:.35rem;cursor:pointer;color:var(--smoke);
    transition:color .2s ease;
  }
  .br-nav-toggle:hover,.br-nav-toggle[aria-expanded="true"]{color:var(--chalk)}
  .br-nav-toggle svg{width:22px;height:22px}

  /* `.br-head-in` is a space-between row, and below 900px it holds three
     items: wordmark, tools, toggle. Space-between then spreads the free width
     evenly, which parked the account and cart icons in the middle of the bar,
     a long way from the menu button they belong beside. An auto margin gives
     all of that space to the left instead: wordmark on one edge, the three
     controls together on the other. */
  .br-head-tools{order:2;margin-left:auto;gap:1rem}
  .br-head-in{gap:1rem}
  .br-nav-toggle{margin-left:.15rem}

  /* Full screen and instant. No slide, no fade: the panel is either the
     whole screen or it is not there. */
  .br-nav{
    display:flex;flex-direction:column;gap:0;
    /* the desktop row centres its items vertically; a column would read that
       as centring them horizontally */
    align-items:stretch;align-self:auto;
    position:fixed;inset:var(--br-chrome-top,0) 0 0 0;z-index:70;
    padding:calc(78px + 1.25rem) var(--gutter)
            calc(3rem + env(safe-area-inset-bottom, 0px));
    background:var(--void);
    opacity:0;pointer-events:none;visibility:hidden;
    overflow-y:auto;overscroll-behavior:contain;
  }
  /* `bottom:0` on a fixed element answers to the *layout* viewport, and on a
     phone that is the tall one — the height the page has when the browser's
     own bars are retracted. So the last inch of the panel sat behind the
     address bar and the list looked cut off at the bottom. `dvh` is the height
     actually on screen right now, bars included, and it is what this should
     have been measured against. Kept behind @supports so a browser without it
     falls back to the inset above rather than to no height at all. */
  @supports (height:100dvh){
    .br-nav{bottom:auto;height:calc(100dvh - var(--br-chrome-top, 0px))}
  }
  .br-nav.is-open{opacity:1;pointer-events:auto;visibility:visible}
  /* the toggle and the wordmark stay above the panel: one closes it, the
     other keeps the header from vanishing while the menu is open */
  .br-nav-toggle{position:relative;z-index:80}
  .br-brand{position:relative;z-index:80}
  .br-nav-toggle .br-icon-close{display:none}
  .br-nav-toggle[aria-expanded="true"] .br-icon-open{display:none}
  .br-nav-toggle[aria-expanded="true"] .br-icon-close{display:inline}
  .br-nav a{
    font-size:.9375rem;letter-spacing:.16em;
    padding:1.05rem 0;border-bottom:1px solid var(--iron);color:var(--smoke);
  }
  .br-nav a::after{display:none}
  .br-nav a[aria-current="page"]{color:var(--chalk)}
  body.br-nav-open{overflow:hidden}

  /* A submenu in the panel is a section of the same column, not a card
     floating over it: the row keeps the divider, the chevron sits at its right
     edge as a 44px target, and the sub-items appear underneath, indented.
     Nothing overlays anything, so scrolling the panel never cuts a link off.
     Closed is `display:none` rather than a height animation — a column of
     links has no fixed height to animate to, and the panel is already an
     instant, full-screen thing. */
  .br-nav-item{display:block;align-self:auto}
  .br-nav-row{
    display:flex;align-items:center;justify-content:space-between;
    border-bottom:1px solid var(--iron);
  }
  .br-nav-row > a{flex:1 1 auto;border-bottom:0}
  .br-sub-toggle{flex:none;width:44px;height:44px;padding:0}
  .br-sub{
    position:static;min-width:0;padding:0;
    background:none;backdrop-filter:none;border:0;
    transform:none;transition:none;
    display:none;opacity:1;visibility:visible;pointer-events:auto;
  }
  .br-nav-item.is-open > .br-sub,
  .br-nav-item:focus-within > .br-sub{display:flex;flex-direction:column}
  .br-sub > a{padding-left:1.25rem;font-size:.875rem;letter-spacing:.14em}

  /* The search stays in the bar at every width now. It used to be dropped here
     and reprinted inside the menu panel, because three icons plus the wordmark
     plus the toggle did not fit — the wordmark gives up the width instead (see
     the rules under 620px), and the reader gets one search instead of two. */
  .br-search-toggle{padding:.35rem}
  /* The overlay is the screen, so its sheet answers to the panel, not the bar. */
  .br-search-sheet{gap:.9rem}
}

/* On a small phone the header bar does not add up. Measured at 360px: wordmark
   194 + gap 32 + two icons 83 + gap 32 + menu toggle 33 = 374, inside 320px of
   usable width — the toggle fell off the right edge, and it did so before the
   search was ever added to it. The wordmark is the half worth giving back: at
   54% of the screen it was oversized anyway. */
@media (max-width:620px){
  .br-head-in{gap:.75rem}
  .br-head-tools{gap:.6rem}
  .br-icon-btn{padding:.3rem}
  .br-brand-word b,
  .br-brand-word span{font-size:.8rem;letter-spacing:.14em;margin-right:-.14em}
}
/* Small phones, where the bar now carries a third icon. The wordmark keeps
   giving: it is the one thing here that still reads at two thirds the size. */
@media (max-width:400px){
  .br-brand-word b,
  .br-brand-word span{font-size:.68rem;letter-spacing:.1em;margin-right:-.1em}
  .br-head-tools{gap:.45rem}
  .br-icon-btn svg{width:17px;height:17px}
  .br-nav-toggle svg{width:20px;height:20px}
}


/* ============================================================
   WP ADMIN BAR
   The bar is fixed at the top of the viewport, and so is the
   site header — without this they occupy the same 32px and the
   header is unusable while logged in. Everything the theme
   pins to the top reads one variable.
   ============================================================ */
body.admin-bar{--br-chrome-top:32px}
body.admin-bar .br-site-head{top:var(--br-chrome-top)}
body.admin-bar .br-rail{top:var(--br-chrome-top)}

@media screen and (max-width:782px){
  body.admin-bar{--br-chrome-top:46px}
}
/* below 600px WordPress lets the bar scroll away, so nothing needs offsetting */
@media screen and (max-width:600px){
  body.admin-bar{--br-chrome-top:0px}
}

/* ============================================================
   MAILING LIST CONSENT
   ============================================================ */
.br-consent{
  flex-basis:100%;display:flex;align-items:flex-start;gap:.6rem;
  margin-top:.35rem;
}
.br-consent input[type="checkbox"]{
  appearance:none;-webkit-appearance:none;
  width:16px;height:16px;flex:none;margin:2px 0 0;cursor:pointer;
  border:1px solid var(--iron-lit);background:var(--surface);
  transition:background-color .18s ease,border-color .18s ease;
}
.br-consent input[type="checkbox"]:checked{
  background:var(--bone);border-color:var(--bone);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.4l3 3 6-6.8' fill='none' stroke='%230A0908' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:14px;background-position:center;background-repeat:no-repeat;
}
.br-consent label{
  font-family:var(--mono);font-size:.6875rem;line-height:1.6;
  letter-spacing:.04em;color:var(--smoke);cursor:pointer;
}
.br-consent a{color:var(--chalk);border-bottom:1px solid var(--iron-lit)}
.br-consent a:hover{border-bottom-color:var(--bone)}
