/*
 * Self-hosted webfonts. GENERATED by build/fetch-fonts.js - do not edit by hand.
 *
 * Served from our own origin so there is no third-party DNS, TLS or round trip
 * before text can be painted in the real typeface. Latin subset only. The icon font
 * is subset to the 42 icons the site actually uses.
 */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/inter-variable.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 600 900;
  font-display: swap;
  src: url('../fonts/montserrat-variable.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('../fonts/material-symbols-outlined.woff2') format('woff2');
}

/*
 * The icon utility class. NOT generated by fetch-fonts.js — added by hand and kept here
 * deliberately.
 *
 * Declaring @font-face is not enough: every icon in the markup is a <span
 * class="material-symbols-outlined">person</span>, and without this rule the browser
 * renders the ligature name as literal text — the header showed the word "person" where
 * the account icon should be, on every page of the site.
 *
 * It lived in site.css, which the child theme deliberately does not ship. The Bricks
 * converter could not map it to an element or a class, so it put it in a "HTML/CSS"
 * residue block on each page — which the build process then deletes. Its correct home is
 * here, next to the @font-face it depends on: it is a global typographic concern, it is
 * identical on every page, and keeping it out of page content means ROAR cannot break it
 * from the builder.
 */
.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-weight: 400;
  font-style: normal;
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  vertical-align: middle;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
}

/*
 * List reset, carried over from the static build's baseline.
 *
 * The static site is built on Tailwind, whose preflight includes
 * `menu, ol, ul { list-style: none; margin: 0; padding: 0 }`. Every list in the design
 * is a layout device — breadcrumbs, nav menus, feature checklists — styled with flex and
 * an explicit icon, never with a marker.
 *
 * That preflight does not come across: build/extract-for-bricks.js keeps only rules whose
 * selector mentions a class the markup uses, and these are bare element selectors. Bricks
 * zeroes paragraph margins itself but does not touch lists, so breadcrumbs rendered as
 * "1. Home  2.  3. Contact Our RTO" — the separator chevron counted as an item.
 *
 * Scoped to Bricks-rendered content so it cannot affect wp-admin.
 *
 * NOT scoped with #brx-content, deliberately. An id selector outranks every utility class,
 * so a list that asks for markers cannot get them back. The blog articles are the case that
 * matters: their bullet lists carry `list-disc pl-md my-md`, and under the id-scoped version
 * they rendered as unindented, unmarked runs of text — the reset silently beat the design.
 *
 * An attribute selector on the Bricks element prefix has the same reach and the same
 * (0,1,1) weight as the element scoping, so any utility on the list itself wins on class
 * count alone, whatever the load order.
 */
[class*="brxe-"] ol,
[class*="brxe-"] ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
 * Make Bricks' Section element behave like a plain <section>.
 *
 * Bricks styles every Section as a centred flex column:
 *
 *     .brxe-section { display:flex; flex-direction:column; align-items:center; ... }
 *
 * The static build's sections are ordinary blocks whose children are laid out by their
 * own utility classes. When the converter turns a <section> into a Bricks Section, that
 * flex centring comes along uninvited — on the course page it centred every heading
 * inside its card ("Course Overview", "Entry Requirements"), which reads as a design
 * choice rather than as a bug.
 *
 * Only the three layout declarations are reset; the auto margins and full width are
 * Bricks' own and are wanted. Specificity here matches the utilities exactly, and this
 * file is enqueued first, so a section that genuinely carries `flex` or `items-center`
 * still wins from utilities.css.
 */
html:root .brxe-section {
  display: block;
  flex-direction: initial;
  align-items: initial;
}

/*
 * Baseline corrections, found by comparing the built pages against the approved
 * index.html with build/compare-layout.js. Both are the same kind of problem: Bricks'
 * element defaults differ from what a plain HTML document does, and the design was
 * authored against plain HTML.
 *
 * 1. LAYOUT ELEMENTS
 *
 * Bricks styles Block and Container the way it styles Section — a flex column, and with
 * `align-items: flex-start`, which makes every child shrink to its own content width
 * instead of filling the parent. On the testimonial cards that pulled each author's name
 * in from 325px to 91px and left it looking centred.
 *
 * Reset to plain block layout. Any element that genuinely wants flex carries `flex` and
 * `flex-col` in its own classes, and utilities.css is enqueued after this file, so those
 * still win.
 *
 * 2. BLOCK MARGINS
 *
 * Tailwind's preflight zeroes the margins on these elements and the design assumes it.
 * The preflight as a whole is excluded on purpose — it also resets headings and links in
 * ways that fight Bricks' own elements — so only the margin rule is carried across, plus
 * the blockquote padding, which browsers set to 40px and which pushed every testimonial
 * quote inwards.
 *
 * These use element selectors deliberately, at lower specificity than the utilities. A
 * first attempt scoped them with #brx-content, whose id outranks every utility class and
 * silently stripped mb-md from eighteen elements — trading one spacing bug for another.
 */
html:root .brxe-block,
html:root .brxe-container {
  display: block;
  flex-direction: initial;
  align-items: initial;
}

html:root blockquote,
html:root dd,
html:root dl,
html:root figure,
html:root hr,
html:root pre {
  margin: 0;
}

html:root blockquote {
  padding-inline: 0;

  /*
   * Bricks styles the bare element: `blockquote { border-left: 4px solid }`, in a neutral grey
   * inherited from the body text colour. The design uses blockquote for two different things
   * and neither wants that:
   *
   *   - testimonial quotes carry no border class at all, so Bricks' grey stripe was the only
   *     thing drawing there. This is the "grey line inside the customer's review box" ROAR
   *     reported — it sat to the left of the quote, full height of the flex-grow box.
   *
   *   - blog pull-quotes ask for `border-l-4 border-primary`, a 4px stripe in ROAR orange. They
   *     were getting Bricks' grey width with the design's colour fighting over the top.
   *
   * Zeroing it here fixes both. Specificity is (0,1,1) — above Bricks' bare element selector
   * (0,0,1), below the `html:root .border-l-4` utility (0,2,1) — so the pull-quotes still get
   * their 4px and the testimonials get nothing, which is what each one asks for.
   */
  border-left-width: 0;
}

/*
 * Second pass of baseline corrections, from build/compare-layout.js.
 *
 * FIGCAPTION
 *
 * Bricks centres figcaption. A bare <figcaption> computes `text-align: center` on a built
 * page and `start` on the approved design, which pulled every testimonial author's name to
 * the middle of its card. The rule lives inside `@layer bricks`, so it does not appear when
 * enumerating stylesheet rules unless the walk descends into layer blocks — it looked for a
 * while as though nothing was setting it at all. Unlayered styles beat layered ones
 * regardless of specificity, so this is enough to undo it.
 *
 * TEXT LINKS
 *
 * `.brxe-text-link` is `display: flex` with `gap: 5px`. The design's buttons are
 * inline-block with no gap, so every call to action gained a 5px gap and centred contents.
 *
 * IMAGES
 *
 * `.brxe-image` is `inline-block`; Tailwind's preflight makes images `block`. As an inline
 * box the hero picked up baseline spacing and came out 640px tall instead of 780px.
 *
 * BLOCK MARGINS
 *
 * The rest of the margin reset the design assumes from preflight. Kept to element
 * selectors so the utilities, which are enqueued after this file, continue to win.
 */
html:root figcaption {
  text-align: inherit;
}

html:root .brxe-text-link {
  display: revert;
  gap: normal;
  align-items: normal;
  justify-content: normal;
}

html:root .brxe-image,
html:root img,
html:root svg,
html:root video,
html:root canvas {
  display: block;
}

html:root p,
html:root h1,
html:root h2,
html:root h3,
html:root h4,
html:root h5,
html:root h6 {
  margin: 0;
}

/*
 * Buttons centre their own text in every browser's default stylesheet, and the design
 * relies on it — the carousel's round prev/next buttons hold a single icon glyph and
 * nothing else centres it horizontally. Bricks resets it to `start`, which left both
 * chevrons sitting against the left edge of their 44px circle.
 */
html:root button {
  text-align: center;
}

/*
 * Let an image that is told to fill its container actually fill it.
 *
 * Bricks writes a per-element rule from every image's intrinsic size:
 *
 *     #brxe-xfcdht { width: 1280px; height: 480px }
 *
 * That is sensible on its own — it reserves space and avoids layout shift — but it is an
 * id selector, so it beats every utility class. The design's full-bleed heroes carry
 * `absolute inset-0 w-full h-full object-cover`, and they were rendering at the image's
 * own 1280x480 inside a 1521px section instead of covering it.
 *
 * `!important` is used deliberately and narrowly. Nothing below an id can win, short of
 * adding an id of our own to every image, and the alternative — abandoning Bricks' image
 * element so ROAR loses the media picker — is a worse trade. It applies only where the
 * markup has explicitly asked the image to fill, so an image with its own dimensions is
 * untouched.
 */
html:root .brxe-image.w-full  { width: 100% !important; }
html:root .brxe-image.h-full  { height: 100% !important; }
html:root .brxe-image.w-auto  { width: auto !important; }
html:root .brxe-image.h-auto  { height: auto !important; }

/* ---------------------------------------------------------------------------
 * Course sidebar enquiry form
 *
 * Bricks' form element renders its own markup — .form-group, .label, an input,
 * a .bricks-button — and there is no per-field class control to hang utilities
 * off, so the design's utility stack is restated here against Bricks' own
 * selectors. Values are copied from the utilities they replace, not re-picked:
 *
 *   label   block font-label-md text-label-md mb-xs uppercase text-primary-fixed-dim
 *   input   w-full bg-white/10 border border-white/30 rounded p-sm text-white
 *           placeholder-white/50 font-body-md text-body-md
 *   button  w-full border-2 border-primary-fixed-dim text-primary-fixed-dim py-sm
 *           rounded font-bold font-label-md text-label-md uppercase tracking-widest
 *
 * Scoped to .roar-enquiry-form because this form sits on the dark
 * bg-on-secondary-fixed card. The contact page's form is on white and must not
 * inherit any of this.
 * ------------------------------------------------------------------------- */
html:root .roar-enquiry-form .form-group        { margin-bottom: 12px; }
html:root .roar-enquiry-form .form-group:last-child { margin-bottom: 0; }

html:root .roar-enquiry-form label {
	display:        block;
	margin-bottom:  4px;
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    600;
	letter-spacing: .05em;
	text-transform: uppercase;
	color:          rgb(255 181 160);
}

html:root .roar-enquiry-form .form-group input {
	width:         100%;
	padding:       12px;
	border:        1px solid rgb(255 255 255 / .3);
	border-radius: 8px;
	background:    rgb(255 255 255 / .1);
	color:         #fff;
	font-family:   Inter;
	font-size:     16px;
	line-height:   24px;
	font-weight:   400;
}

html:root .roar-enquiry-form .form-group input::placeholder { color: rgb(255 255 255 / .5); }

/* The design's focus:ring-2 focus:border-transparent. Kept as a real outline so it
   survives forced-colors mode, where box-shadow rings disappear entirely. */
html:root .roar-enquiry-form .form-group input:focus {
	outline:        2px solid rgb(255 181 160);
	outline-offset: 0;
	border-color:   transparent;
}

html:root .roar-enquiry-form .submit-button-wrapper { width: 100%; }

html:root .roar-enquiry-form button[type="submit"] {
	width:          100%;
	padding:        12px 0;
	border:         2px solid rgb(255 181 160);
	border-radius:  8px;
	background:     transparent;
	color:          rgb(255 181 160);
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    700;
	letter-spacing: .1em;
	text-transform: uppercase;
	transition:     background-color .15s, color .15s;
}

html:root .roar-enquiry-form button[type="submit"]:hover,
html:root .roar-enquiry-form button[type="submit"]:focus-visible {
	background: rgb(255 181 160);
	color:      rgb(16 28 42);
}

/* ---------------------------------------------------------------------------
 * Paragraph spacing inside rich text
 *
 * `html:root p { margin: 0 }` above strips WordPress's default paragraph
 * margins, which is right for the converted design — every paragraph there
 * carries its own spacing utility. But ACF WYSIWYG fields emit bare <p> tags
 * with no classes, so a course overview ROAR later splits into two paragraphs
 * would run together with no gap at all.
 *
 * Restated only where paragraphs actually follow one another, so the single
 * paragraph case — every course today — is unaffected.
 * ------------------------------------------------------------------------- */
html:root .brxe-text-basic p + p { margin-top: 16px; }

/* ---------------------------------------------------------------------------
 * Let a full-bleed block actually bleed
 *
 * Bricks caps its elements at `max-width: 100%`. That is a sensible default and
 * harmless almost everywhere, but it silently defeats the negative-margin
 * full-bleed pattern: `-mx-margin-mobile px-margin-mobile` is meant to pull a
 * block out past its container's padding and re-pad it, so the content lines up
 * while the background runs edge to edge.
 *
 * Capped at 100% the margins still apply — the element just shifts left instead
 * of widening. On the homepage's testimonial marquee that made the viewport
 * 343px instead of 375px at phone width, so every card was 27px narrow and every
 * quote wrapped onto an extra line. It looked like a typography problem.
 *
 * Keyed on the negative-margin utility itself, which is the markup's own signal
 * that this element is meant to be wider than its parent. Nothing else on the
 * site uses the pattern, so nothing else is affected — and if a second one is
 * added later it is covered without anyone remembering this rule exists.
 * ------------------------------------------------------------------------- */
html:root [class*="-mx-margin-mobile"] { max-width: none; }

/* ---------------------------------------------------------------------------
 * The shop's SALE badge is a pill, not a banner
 *
 * Moving the positioning onto the Bricks wrapper fixed the product photos being
 * pushed off centre, but introduced a second fault I did not check for: Bricks
 * gives `.brxe-shortcode` `width: 100%`, so the absolutely positioned wrapper
 * spanned the whole card and the badge inside it stretched into a full-width
 * orange bar across the top of every discounted product.
 *
 * `fit-content` restores the shrink-to-fit an absolutely positioned box would
 * have had on its own. Keyed on the element's own class, which this project
 * controls because it comes from the id set in build-shop-archive.php.
 * ------------------------------------------------------------------------- */
html:root .brxe-shopbadge {
	width: fit-content;
}

/* ---------------------------------------------------------------------------
 * Desktop nav links: the design's label type, not the body default
 *
 * Bricks builds the nav from a WordPress menu and gives the links no classes at
 * all, so they fell through to the body font. Measured against the approved
 * design they were wrong on four counts at once:
 *
 *              design                 was
 *   size       14px                   16px
 *   weight     500                    400
 *   tracking   0.7px                  none
 *   colour     rgb(83 95 112)         rgb(25 28 29)
 *
 * Individually small; together they made the nav read as body copy sitting in
 * the header rather than as navigation, which is what ROAR was seeing.
 *
 * This is `font-label-md text-label-md text-secondary font-medium` from the
 * design, restated against Bricks' own selectors because the classes cannot be
 * put on markup this file does not control.
 *
 * Kept at (0,2,3) so the current-page rule further down — which is id-scoped and
 * therefore (1,2,3) — still wins and keeps its ROAR-orange weight 700 underline.
 * ------------------------------------------------------------------------- */
html:root .bricks-nav-menu > li > a,
html:root .bricks-nav-menu > li > .brx-submenu-toggle > a {
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    500;
	letter-spacing: 0.7px;
	color:          rgb(83 95 112);   /* the design's text-secondary */
}

/* ---------------------------------------------------------------------------
 * The hero <picture> has to behave like the <img> it replaced
 *
 * <picture> is an inline element with no box of its own, so `w-full h-full` on
 * the <img> inside resolved against the wrong ancestor — the photo rendered
 * 1690px wide inside a 1536px viewport and pushed the hero into horizontal
 * overflow. Making the picture a block that fills its parent gives the img the
 * containing block it expects, and the layout matches the original <img>.
 * ------------------------------------------------------------------------- */
html:root .roar-hero-picture {
	display:  block;
	position: absolute;
	inset:    0;
	width:    100%;
	height:   100%;
}

/* ---------------------------------------------------------------------------
 * Mobile menu: "Our Courses" and its chevron are one control
 *
 * Bricks lays the row out as `justify-content: space-between`, which parks the
 * label hard left and the chevron hard right against the panel edge. They look
 * like two separate controls because they read as two separate controls, and
 * ROAR asked for them merged — the chevron belongs to the words.
 *
 * Tapping either now opens the submenu (assets/js/chrome.js forwards the label
 * to the toggle), so grouping them is honest rather than decorative.
 * ------------------------------------------------------------------------- */
html:root .bricks-mobile-menu .brx-submenu-toggle {
	justify-content: flex-start;
	gap:             8px;
}

/*
 * The anchor has to stop growing, or `justify-content` has nothing to distribute: Bricks gives
 * the label `flex: 1`, which fills the row and parks the chevron against the panel edge however
 * the row is justified. This is why the first attempt at grouping them did nothing visible.
 */
html:root .bricks-mobile-menu .brx-submenu-toggle > a {
	flex:      0 1 auto;
	min-width: 0;
}

/*
 * NO `pointer-events: none` here. It was added so the row could own every tap, and it took away
 * the one part that had always worked — the chevron's own native toggle — leaving the whole row
 * dependent on JavaScript forwarding. When that forwarding did not fire on a real phone, nothing
 * opened at all.
 *
 * The chevron keeps its own behaviour. chrome.js covers the label and the gap, and falls back to
 * setting the state itself if Bricks does not respond.
 */
html:root .bricks-mobile-menu .brx-submenu-toggle > button {
	flex:                0 0 auto;
	margin-inline-start: 0;
}

/*
 * The row reads as one control because it behaves as one: chrome.js forwards a tap anywhere in
 * it to the toggle, so the label, the chevron and the gap between them all open the submenu.
 * The cursor and the full-width hit area are what say so.
 */
html:root .bricks-mobile-menu .brx-submenu-toggle {
	cursor: pointer;
}

/* ---------------------------------------------------------------------------
 * Mobile menu: the close button had nowhere of its own to sit
 *
 * Bricks pins the toggle to the top right of the panel, and the panel's first
 * item starts at the very top — so the X landed on the "Our Courses" row,
 * between its label and its chevron. Three tap targets in one line, one of
 * which closes the menu you have just opened.
 *
 * The list is pushed down by one row's worth so the X gets a band to itself.
 * Done with padding on the list rather than by moving the button, because the
 * button's position is Bricks' own and moving it would fight the panel's open
 * and close animation.
 * ------------------------------------------------------------------------- */
html:root .bricks-mobile-menu-wrapper .bricks-mobile-menu {
	padding-top: 64px;
}

/* ---------------------------------------------------------------------------
 * Mobile menu: a labelled Close button instead of a bare X
 *
 * ROAR asked for something better than the X and left the how to me.
 *
 * A naked glyph is the least discoverable control you can put on a panel: it
 * carries no word, its hit area is only as big as the icon, and on a dark panel
 * a thin cross reads as decoration. It was also the site's link blue, which
 * belongs to links, not to controls.
 *
 * So: a pill with a border, a real label, and a 44px minimum height — the size
 * below which a touch target starts producing mis-taps. It is the same shape
 * language as the buttons everywhere else on the site, which is the point; a
 * control should look like the other controls.
 *
 * The word is added with ::after rather than by editing Bricks' markup, which
 * this file cannot reach. `aria-label="Close mobile menu"` is already on the
 * button, so a screen reader was never the audience for this fix — sighted
 * thumbs were.
 *
 * NOT VERIFIED AT MOBILE WIDTH. The browser here will not resize below the
 * desktop breakpoint, so Bricks' open-state geometry could not be observed.
 * Appearance only is changed; position is left entirely to Bricks.
 * ------------------------------------------------------------------------- */
/*
 * EVERY rule here is scoped to [aria-expanded="true"] — the OPEN state — and none of them
 * touch `display`. Both constraints are the result of getting this wrong.
 *
 * The first version styled `.bricks-mobile-menu-toggle` unconditionally and opened with
 * `display: inline-flex`. That overrode Bricks' own `display: none`, so the button existed on
 * desktop too: an invisible 44px pill (white text on a white header) sitting in the header's
 * flex row, pushing "Our Courses / Shop / Blog / Contact Us" out of vertical centre. On mobile
 * the same white-on-white made the closed hamburger vanish entirely, leaving no way to open the
 * menu at all. One rule, two bugs, and the worse of the two was silent.
 *
 * Bricks owns whether this button is shown and where. This file owns only what it looks like
 * once the panel is open and it is sitting on a dark background.
 */
/*
 * Plain text, no pill.
 *
 * The bordered pill was my idea and ROAR did not want it — with Bricks' own round button
 * background showing through underneath, it read as a circle sitting on top of the word rather
 * than a button around it. A word on its own is enough here: it is the only control in that
 * corner, it sits in its own band, and "Close" needs no chrome to be understood.
 *
 * The 44px minimum stays. It is the smallest a touch target can be before mis-taps start, and
 * it is invisible either way.
 */
/*
 * The burger itself: ROAR orange, not the near-black Bricks gives its three bars.
 *
 * Drawn as three `<span>` bars with a background colour rather than an icon font, so the colour
 * goes on the bars — `color` on the button does nothing.
 *
 * Applies in the closed state only. Once open the bars are hidden and the word "Exit" replaces
 * them, and that is styled separately below.
 */
html:root .bricks-mobile-menu-toggle .bar-top,
html:root .bricks-mobile-menu-toggle .bar-center,
html:root .bricks-mobile-menu-toggle .bar-bottom {
	background-color: rgb(170 55 18);   /* the design's primary */
}

html:root .bricks-mobile-menu-toggle[aria-expanded="true"] {
	align-items:    center;
	min-height:     44px;
	/*
	 * 28px on the right so "Exit" sits clear of the edge of the screen. It is the last thing in
	 * the header row, so nothing else provides that separation, and 16px was still reading as
	 * tight against the bezel on a phone.
	 */
	padding:        8px 28px 8px 4px;
	border:         0;
	border-radius:  0;
	background:     none;
	box-shadow:     none;
	color:          rgb(186 26 26);     /* the design's error red */
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    700;
	letter-spacing: 0.7px;
}

/*
 * The word replaces the icon rather than joining it.
 *
 * Bricks draws its X with absolutely positioned bars inside the button, so adding a label
 * produced the two stacked on top of each other — ROAR's screenshot showed a button reading
 * "✕lose". A control needs one of the two, and the word is the one that survives being small,
 * dark-on-dark, or unfamiliar.
 */
html:root .bricks-mobile-menu-toggle[aria-expanded="true"] > * {
	display: none;
}

html:root .bricks-mobile-menu-toggle[aria-expanded="true"]::before,
html:root .bricks-mobile-menu-toggle[aria-expanded="true"]::after {
	content: none;
}

html:root .bricks-mobile-menu-toggle[aria-expanded="true"]::after {
	content:     "Exit";
	display:     block;
	white-space: nowrap;
}

/* ---------------------------------------------------------------------------
 * Mobile: the burger belongs beside the cart
 *
 * Bricks puts the mobile toggle where the desktop nav was, which is the middle
 * of the header — so the three controls read as logo, burger, then account and
 * cart, with the burger stranded on its own. ROAR asked for it grouped with the
 * cart, which is also where a thumb reaching for the top right expects it.
 *
 * `order` on the flex children rather than moving markup: the header is a
 * Bricks template and its element order is ROAR's to edit in the builder. Auto
 * margin on the logo pushes it left, leaving the account, cart and burger
 * together on the right.
 *
 * 991px is Bricks' tablet_portrait breakpoint — the width at which it swaps the
 * nav for the toggle. Above it the toggle is display:none and none of this
 * applies.
 * ------------------------------------------------------------------------- */
@media ( max-width: 991px ) {
	html:root #brx-header .brxe-nav-menu {
		order: 3;
	}

	html:root #brx-header .brxe-logo {
		margin-right: auto;
	}
}

html:root .bricks-mobile-menu-toggle[aria-expanded="true"]:hover,
html:root .bricks-mobile-menu-toggle[aria-expanded="true"]:focus-visible {
	text-decoration: underline;
	text-underline-offset: 4px;
}

/*
 * Tapping the page behind the panel also closes it — Bricks' own overlay. It is
 * the gesture most people reach for first, so it is worth making sure the
 * overlay is actually catching taps rather than sitting under the panel.
 */
html:root .bricks-mobile-menu-overlay {
	cursor: pointer;
}

/* ---------------------------------------------------------------------------
 * Student Handbook: the browser's PDF viewer, not ours
 *
 * See inc/handbook.php for why this is an <object> rather than pdf.js. The
 * embed is desktop-only: mobile browsers will not render a PDF inside an
 * element, so phones get the button instead of a blank grey box.
 * ------------------------------------------------------------------------- */
html:root .roar-handbook-embed {
	display:    block;
	width:      100%;
	height:     70vh;
	min-height: 480px;
	border:     0;
}

html:root .roar-handbook-fallback,
html:root .roar-handbook-small {
	display:         flex;
	align-items:     center;
	justify-content: center;
	padding:         48px 24px;
}

/* The small-screen button is the only one shown below the breakpoint. */
html:root .roar-handbook-small { display: none; }

@media ( max-width: 767px ) {
	html:root .roar-handbook-embed { display: none; }
	html:root .roar-handbook-small { display: flex; }
}

/* ---------------------------------------------------------------------------
 * An empty cart should be empty
 *
 * WooCommerce's block cart fills an empty cart with a "New in store" grid —
 * product images, SALE badges, prices and Add to cart buttons. ROAR asked for
 * none of it: someone who has just emptied their cart, or landed there by
 * accident, is being sold to rather than helped, and the block is stock
 * WooCommerce styling that matches nothing else on the site.
 *
 * The "New in store" heading is hidden alongside the grid; leaving it above
 * nothing would read as something that had failed to load.
 *
 * `:not(.wc-block-cart__empty-cart__title)` is load-bearing. Without it this
 * also hid "Your cart is currently empty!", which is the one thing the page
 * exists to say — the cart went from over-selling to completely blank.
 * ------------------------------------------------------------------------- */
/*
 * The "Cart" page title.
 *
 * WooCommerce prints it with no container of its own, so it sat jammed into the top-left corner
 * against the header with everything beneath it centred — the one thing on the page that was
 * not lined up with anything. Given the site's own container, the design's page-title size, and
 * room to breathe above and below.
 *
 * This is interim. The approved design (cart.html) opens with a dark hero carrying "Your Cart",
 * not a bare heading on the page background — that arrives with the cart page build (task #28).
 */
/*
 * It is a bare <h1> with no class at all, straight inside #brx-content — not the
 * `.entry-title` a first attempt assumed, which matched nothing and left the heading exactly
 * where it was. Selected by the body class WooCommerce sets on these pages instead.
 */
html:root body.woocommerce-cart #brx-content > h1,
html:root body.woocommerce-checkout #brx-content > h1 {
	max-width:  1280px;
	margin:     0 auto;
	padding:    48px 16px 16px;
	box-sizing: border-box;
}

@media ( min-width: 768px ) {
	html:root body.woocommerce-cart #brx-content > h1,
	html:root body.woocommerce-checkout #brx-content > h1 {
		padding: 64px 24px 16px;
	}
}

/*
 * With the product grid gone, the empty state had nothing holding the page open: the sad face
 * and one line of text sat directly on top of the footer, and the "Cart" title was left
 * stranded top-left while everything under it was centred.
 *
 * The block gets real vertical room and everything in it lines up on one axis. `py-xl` is the
 * design's own largest section padding, which is what the rest of the site uses when a section
 * has little in it.
 */
html:root .wp-block-woocommerce-empty-cart-block {
	padding-block: 64px 96px;
	text-align:    center;
}

html:root .wp-block-woocommerce-empty-cart-block .wc-block-cart__empty-cart__title {
	margin-inline: auto;
}

/*
 * The sad-face icon is a ::before on the title, absolutely positioned by WooCommerce and so
 * pinned to the left of a centred heading. Centred with the text it belongs to.
 */
html:root .wp-block-woocommerce-empty-cart-block .with-empty-cart-icon::before {
	position:      static;
	display:       block;
	margin:        0 auto 24px;
	transform:     none;
}

html:root .wp-block-woocommerce-empty-cart-block .wp-block-heading:not( .wc-block-cart__empty-cart__title ),
html:root .wp-block-woocommerce-empty-cart-block .wc-block-grid,
html:root .wp-block-woocommerce-empty-cart-block .wp-block-woocommerce-product-new,
html:root .wp-block-woocommerce-empty-cart-block .wp-block-woocommerce-product-best-sellers,
html:root .wp-block-woocommerce-empty-cart-block .wp-block-woocommerce-product-on-sale,
html:root .wp-block-woocommerce-empty-cart-block .wp-block-woocommerce-product-top-rated,
html:root .wp-block-woocommerce-empty-cart-block .wc-block-product-template,
html:root .wp-block-woocommerce-empty-cart-block .wp-block-query {
	display: none;
}

/* ---------------------------------------------------------------------------
 * WooCommerce's own pages need the site's page margins
 *
 * Single product, cart and checkout are rendered by WooCommerce, not by a
 * Bricks template, so they never picked up the container the rest of the site
 * uses. On a phone that left the title, price and description running into both
 * edges of the screen with no margin at all.
 *
 * `margin-inline: auto` with the design's own container width and mobile
 * margin, so these pages line up with every other page rather than getting
 * their own spacing.
 * ------------------------------------------------------------------------- */
html:root .woocommerce div.product,
html:root .wp-block-woocommerce-cart,
html:root .wp-block-woocommerce-checkout,
html:root .woocommerce-notices-wrapper,
html:root .woocommerce-breadcrumb {
	max-width:      1280px;   /* the design's container-max */
	margin-inline:  auto;
	padding-inline: 16px;     /* the design's margin-mobile */
	box-sizing:     border-box;
}

/* ---------------------------------------------------------------------------
 * Course tabs: the highlight follows aria-selected
 *
 * The converted markup hard-codes the active look on the first tab
 * (`text-primary border-primary`) and the inactive look on the second
 * (`border-transparent`), because in the static build tab one was simply the
 * one showing. assets/js/tabs.js correctly swaps `aria-selected` and the panel
 * visibility when a tab is clicked — but nothing ever moved those classes, so
 * clicking "Additional Information" showed the right panel while "Description"
 * stayed orange and underlined. The page said one thing and looked like another.
 *
 * Driving the styling from `aria-selected` rather than from a class means the
 * appearance cannot disagree with the state: the attribute IS the state, and
 * tabs.js already maintains it. It also keeps the fix out of the JavaScript,
 * where a second source of truth would be one more thing to keep in step.
 *
 * (0,3,1), so it outranks the `text-primary` / `border-primary` utilities at
 * (0,2,1) that are still sitting on the markup.
 * ------------------------------------------------------------------------- */
/*
 * The colours are NOT set here. assets/js/tabs.js moves `text-primary` and `border-primary`
 * between the tabs, because those utility classes are already on the markup and were the thing
 * that never moved. A rule on `[aria-selected]` was tried first and is deliberately not kept:
 * two mechanisms competing to colour the same element is how this kind of thing drifts.
 *
 * What stays here is only what the classes do not cover.
 */
html:root [role="tab"] {
	cursor: pointer;
}

html:root [role="tab"]:hover {
	color: rgb(170 55 18);
}

/* ---------------------------------------------------------------------------
 * No "0" on the cart before the count is known
 *
 * The badge is not in the server HTML at all — Bricks injects the mini cart
 * client-side, so on every page load the markup appears with a count of 0 and
 * is corrected a moment later. That correction is the flicker ROAR was seeing.
 *
 * Hidden by default and shown only once something has marked it `show`, so the
 * badge's first appearance is the correct number rather than a zero on its way
 * to being right. chrome.js clears `show` at zero as well — see updateCartLabel
 * — because a cached fragment can arrive already carrying it.
 * ------------------------------------------------------------------------- */
html:root .mini-cart-link [class*="cart-count"] {
	display: none;
}

html:root .mini-cart-link [class*="cart-count"].show {
	display: flex;
}

/* ---------------------------------------------------------------------------
 * Back-to-top: keep it still during momentum scrolling
 *
 * ROAR reported it drifting with the page on some phones rather than staying
 * put. The markup is correct — it is `position: fixed`, a direct child of body,
 * with no transformed ancestor to trap it — so this is not a containing-block
 * problem, which is the usual cause and was checked first.
 *
 * It is the other one: on iOS Safari and some Android browsers, a fixed element
 * that has not been promoted to its own compositor layer gets rasterised
 * together with the page. During momentum scrolling the compositor moves that
 * whole layer and only corrects the fixed element when the scroll settles, so
 * it visibly slides with the content and snaps back at the end. It is a
 * painting artifact rather than a layout one, which is why it appears on some
 * devices and not others — it depends on the browser's compositing decisions.
 *
 * `translateZ(0)` forces the promotion. `backface-visibility: hidden` stops a
 * related flicker on older WebKit.
 *
 * Not `will-change: transform`, which would ask the browser to hold a layer
 * permanently for an element that is invisible most of the time.
 *
 * NOTE: this cannot be reproduced in the tooling available here — desktop
 * Chrome composites fixed elements correctly regardless. The fix addresses the
 * documented cause; it needs confirming on the device that showed it.
 * ------------------------------------------------------------------------- */
html:root #scrollToTop {
	transform:           translateZ( 0 );
	backface-visibility: hidden;

	/*
	 * Clear the home indicator on phones with a gesture bar. Without this the
	 * button sits under it on an iPhone and is awkward to hit — falls back to
	 * the design's 24px anywhere the inset is not supported.
	 */
	bottom: calc( 24px + env( safe-area-inset-bottom, 0px ) );
	right:  calc( 24px + env( safe-area-inset-right, 0px ) );
}

/* ---------------------------------------------------------------------------
 * The FAQ accordion
 *
 * Built on <details>/<summary>, which the browser already implements — keyboard
 * operable, correctly announced, and findable by in-page search even while
 * collapsed. All this adds is the design's surface and the chevron's rotation.
 * ------------------------------------------------------------------------- */

html:root .roar-faq-item {
	transition: box-shadow .15s, border-color .15s;
}

html:root .roar-faq-item[open] {
	border-color: rgb(170 55 18);
	box-shadow:   0 4px 6px -1px rgb(0 0 0 / 0.08);
}

/*
 * The question size.
 *
 * These were `text-headline-md` — 24px, the same size as a section heading. Eight of them
 * stacked read as eight headings competing with the page title rather than as a list of
 * questions, which is what ROAR was seeing. 18px keeps them clearly the most important thing in
 * each card while letting the h1 stay the most important thing on the page.
 *
 * Montserrat at 700, so they still read as headings — just quieter ones.
 */
html:root .roar-faq-q {
	list-style:  none;
	font-family: Montserrat;
	font-size:   18px;
	line-height: 26px;
	font-weight: 700;
}

@media ( min-width: 768px ) {
	html:root .roar-faq-q {
		font-size:   20px;
		line-height: 28px;
	}
}

html:root .roar-faq-q::-webkit-details-marker {
	display: none;
}

html:root .roar-faq-q:hover {
	color: rgb(170 55 18);
}

/*
 * A real focus ring on the summary. It is the element a keyboard lands on, and without this the
 * only indication is the browser default, which several themes suppress.
 */
html:root .roar-faq-q:focus-visible {
	outline:        2px solid rgb(170 55 18);
	outline-offset: -2px;
}

html:root .roar-faq-icon {
	transition: transform .2s ease;
}

html:root .roar-faq-item[open] .roar-faq-icon {
	transform: rotate( 180deg );
}

/* The last paragraph in an answer should not add space below the panel's own padding. */
html:root .roar-faq-a > :last-child {
	margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
 * The checkout
 *
 * WooCommerce's classic checkout ships almost unstyled: labels sit hard against
 * the field above, rows have no separation, the coupon prompt is a bright blue
 * notice bar that belongs to no palette on this site, and the whole form runs
 * edge to edge with no container. ROAR reported it as needing spacing — it
 * needed the design system.
 *
 * Same treatment as the cart: the site's container, the design's type and field
 * styling, ROAR orange on the one button that completes the purchase.
 * ------------------------------------------------------------------------- */

html:root body.woocommerce-checkout .woocommerce {
	max-width:      1280px;
	margin-inline:  auto;
	padding-inline: 16px;
	padding-bottom: 64px;
	box-sizing:     border-box;
}

@media ( min-width: 768px ) {
	html:root body.woocommerce-checkout .woocommerce {
		padding-inline: 24px;
	}
}

/* ------------------------------------------------------- the coupon prompt */

/*
 * WooCommerce's `.woocommerce-info` is a blue bar with a blue underlined link. Restyled as a
 * quiet panel with the site's own accent, so it reads as an option rather than an alert.
 */
html:root body.woocommerce-checkout .woocommerce-form-coupon-toggle .woocommerce-info,
html:root body.woocommerce-checkout .woocommerce-info {
	display:        flex;
	flex-wrap:      wrap;
	gap:            8px;
	margin:         0 0 32px;
	padding:        16px 20px;
	border:         0;
	border-left:    4px solid rgb(170 55 18);
	border-radius:  8px;
	background:     rgb(247 243 242);
	color:          rgb(82 68 65);
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
}

html:root body.woocommerce-checkout .woocommerce-info::before {
	content: none;   /* WooCommerce's own info glyph */
}

html:root body.woocommerce-checkout .woocommerce-info a {
	color:           rgb(170 55 18);
	font-weight:     700;
	text-decoration: none;
}

html:root body.woocommerce-checkout .woocommerce-info a:hover {
	text-decoration: underline;
}

/* ------------------------------------------------------------ the columns */

@media ( min-width: 1024px ) {
	html:root body.woocommerce-checkout form.checkout {
		display:               grid;
		grid-template-columns: minmax( 0, 1.4fr ) minmax( 0, 1fr );
		gap:                   40px;
		align-items:           start;
	}

	html:root body.woocommerce-checkout #customer_details {
		grid-column: 1;
	}

	html:root body.woocommerce-checkout #order_review_heading,
	html:root body.woocommerce-checkout #order_review {
		grid-column: 2;
	}

	/* WooCommerce floats the billing and shipping halves at 50%; the grid places them now. */
	html:root body.woocommerce-checkout #customer_details .col-1,
	html:root body.woocommerce-checkout #customer_details .col-2 {
		float: none;
		width: 100%;
	}
}

/* -------------------------------------------------------------- headings */

html:root body.woocommerce-checkout .woocommerce h3,
html:root body.woocommerce-checkout #order_review_heading {
	font-family: Montserrat;
	font-size:   24px;
	line-height: 32px;
	font-weight: 700;
	color:       rgb(25 28 29);
	margin:      0 0 20px;
}

/* ---------------------------------------------------------------- fields */

/*
 * The spacing ROAR asked for. WooCommerce's own `.form-row` has a 3px bottom margin, which is
 * what put every label hard against the field above it.
 */
html:root body.woocommerce-checkout .form-row {
	display:        flex;
	flex-direction: column;
	margin:         0 0 20px;
	padding:        0;
}

html:root body.woocommerce-checkout .form-row label {
	margin-bottom:  6px;
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    600;
	color:          rgb(25 28 29);
}

html:root body.woocommerce-checkout .form-row .required {
	color:           rgb(186 26 26);
	text-decoration: none;
}

html:root body.woocommerce-checkout .form-row input.input-text,
html:root body.woocommerce-checkout .form-row textarea,
html:root body.woocommerce-checkout .form-row select,
html:root body.woocommerce-checkout .select2-container .select2-selection {
	width:         100%;
	padding:       12px;
	border:        1px solid rgb(140 113 106);
	border-radius: 8px;
	background:    #fff;
	font-family:   Inter;
	font-size:     16px;
	line-height:   24px;
	color:         rgb(25 28 29);
	box-sizing:    border-box;
}

html:root body.woocommerce-checkout .form-row input.input-text:focus,
html:root body.woocommerce-checkout .form-row textarea:focus,
html:root body.woocommerce-checkout .form-row select:focus {
	outline:        2px solid rgb(170 55 18);
	outline-offset: 0;
	border-color:   transparent;
}

/* Two fields side by side where they belong together, as WooCommerce intends. */
@media ( min-width: 768px ) {
	html:root body.woocommerce-checkout .form-row-first,
	html:root body.woocommerce-checkout .form-row-last {
		display: inline-flex;
		width:   calc( 50% - 10px );
	}

	html:root body.woocommerce-checkout .form-row-first {
		margin-right: 20px;
	}
}

/* ------------------------------------------------------- the order review */

html:root body.woocommerce-checkout #order_review {
	padding:       24px;
	border:        1px solid rgb(224 191 183);
	border-radius: 12px;
	background:    #fff;
	box-shadow:    0 4px 6px -1px rgb(0 0 0 / 0.1);
}

html:root body.woocommerce-checkout #order_review table.shop_table {
	width:           100%;
	border:          0;
	border-collapse: collapse;
	margin-bottom:   20px;
}

html:root body.woocommerce-checkout #order_review table.shop_table th,
html:root body.woocommerce-checkout #order_review table.shop_table td {
	padding:     10px 0;
	border:      0;
	border-bottom: 1px solid rgb(240 236 235);
	font-family: Inter;
	font-size:   15px;
	line-height: 22px;
	text-align:  left;
	color:       rgb(82 68 65);
}

html:root body.woocommerce-checkout #order_review table.shop_table td {
	text-align: right;
	color:      rgb(25 28 29);
}

/*
 * Product names read left, figures read right. WooCommerce puts the line item name in a `td`
 * alongside its price, so the blanket right-alignment above pushed "K2100PT Portable First Aid
 * Kit ×1" against the middle of the panel with a ragged left edge.
 */
html:root body.woocommerce-checkout #order_review table.shop_table td.product-name {
	text-align:  left;
	padding-right: 12px;
}

html:root body.woocommerce-checkout #order_review .order-total th,
html:root body.woocommerce-checkout #order_review .order-total td {
	border-bottom: 0;
	font-size:     18px;
	line-height:   26px;
	font-weight:   700;
	color:         rgb(25 28 29);
}

html:root body.woocommerce-checkout #payment {
	background:    rgb(247 243 242);
	border-radius: 8px;
	padding:       16px;
}

html:root body.woocommerce-checkout #payment ul.payment_methods {
	margin:     0 0 16px;
	padding:    0;
	border:     0;
	list-style: none;
}

html:root body.woocommerce-checkout #place_order {
	width:         100%;
	padding:       14px 24px;
	border:        0;
	border-radius: 8px;
	background:    rgb(170 55 18);
	color:         #fff;
	font-family:   Montserrat;
	font-size:     18px;
	line-height:   28px;
	font-weight:   700;
	cursor:        pointer;
	transition:    background-color .15s;
}

html:root body.woocommerce-checkout #place_order:hover {
	background: rgb(134 34 0);
}

/* ---------------------------------------------------------------------------
 * The single product page
 *
 * There is no design file for this one. shop.html covers the listing and
 * cart.html the cart, so this is composed from the system those two establish
 * rather than matched to a reference: the shop card's white image panel and
 * outline, the course page's tab bar, the cart's primary button, and the
 * design's own type scale throughout. ROAR approved building it this way.
 *
 * WooCommerce's own structure is kept — gallery, summary, tabs — because it is
 * already the two-column arrangement the rest of the site uses and rebuilding
 * it in Bricks would mean reimplementing the gallery and the add-to-cart form
 * for no gain.
 * ------------------------------------------------------------------------- */

html:root .woocommerce div.product {
	padding-block: 32px 64px;
}

/* ------------------------------------------------------------ breadcrumb */

html:root .woocommerce .woocommerce-breadcrumb {
	padding-block: 24px 0;
	font-family:   Inter;
	font-size:     12px;
	line-height:   16px;
	color:         rgb(82 68 65);
}

html:root .woocommerce .woocommerce-breadcrumb a {
	color: rgb(82 68 65);
}

html:root .woocommerce .woocommerce-breadcrumb a:hover {
	color: rgb(170 55 18);
}

/* -------------------------------------------------------------- the layout */

@media ( min-width: 768px ) {
	html:root .woocommerce div.product {
		display:               grid;
		grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
		gap:                   40px;
		align-items:           start;
	}

	html:root .woocommerce div.product .woocommerce-product-gallery,
	html:root .woocommerce div.product .summary {
		float: none;      /* WooCommerce floats these at 48% — same trap as the cart */
		width: 100%;
	}

	html:root .woocommerce div.product .woocommerce-tabs,
	html:root .woocommerce div.product .related,
	html:root .woocommerce div.product .up-sells {
		grid-column: 1 / -1;
	}
}

/* ------------------------------------------------------------- the gallery */

/*
 * The same white panel the shop cards use, so a product looks like itself in both places.
 * `contain` rather than `cover`: these are catalogue photographs on white and cropping them
 * cuts the product in half.
 */
html:root .woocommerce div.product .woocommerce-product-gallery {
	background:    #fff;
	border:        1px solid rgb(224 191 183);
	border-radius: 12px;
	padding:       24px;
	box-sizing:    border-box;
}

html:root .woocommerce div.product .woocommerce-product-gallery img {
	width:      auto;
	max-width:  100%;
	max-height: 480px;
	margin:     0 auto;
	object-fit: contain;
}

/* ------------------------------------------------------------- the summary */

html:root .woocommerce div.product .product_title {
	font-family: Montserrat;
	font-size:   32px;
	line-height: 40px;
	font-weight: 700;
	color:       rgb(25 28 29);
	margin:      0 0 8px;
}

html:root .woocommerce div.product .summary .price {
	display:     flex;
	align-items: baseline;
	gap:         12px;
	flex-wrap:   wrap;
	margin:      0 0 16px;
	font-family: Montserrat;
	font-size:   28px;
	line-height: 36px;
	font-weight: 700;
	color:       rgb(170 55 18);
}

/* The pre-sale price: struck through and quieter, as on the shop cards. */
html:root .woocommerce div.product .summary .price del {
	font-family:     Inter;
	font-size:       16px;
	line-height:     24px;
	font-weight:     400;
	color:           rgb(82 68 65);
	text-decoration: line-through;
}

html:root .woocommerce div.product .summary .price ins {
	text-decoration: none;
	color:           rgb(170 55 18);
}

html:root .woocommerce div.product .woocommerce-product-details__short-description {
	font-family: Inter;
	font-size:   16px;
	line-height: 24px;
	color:       rgb(82 68 65);
	margin:      0 0 24px;
}

/*
 * The long description's feature list gets the shop card's tick treatment, so the bullets a
 * visitor saw on the listing look the same once they are on the product itself.
 */
html:root .woocommerce div.product .woocommerce-Tabs-panel ul,
html:root .woocommerce div.product .woocommerce-product-details__short-description ul {
	list-style: none;
	padding:    0;
	margin:     0 0 16px;
}

html:root .woocommerce div.product .woocommerce-Tabs-panel li,
html:root .woocommerce div.product .woocommerce-product-details__short-description li {
	position:      relative;
	padding-left:  28px;
	margin-bottom: 8px;
	font-family:   Inter;
	font-size:     16px;
	line-height:   24px;
	color:         rgb(82 68 65);
}

html:root .woocommerce div.product .woocommerce-Tabs-panel li::before,
html:root .woocommerce div.product .woocommerce-product-details__short-description li::before {
	content:     "check";
	font-family: "Material Symbols Outlined";
	font-size:   18px;
	line-height: 24px;
	position:    absolute;
	left:        0;
	top:         0;
	color:       rgb(170 55 18);
}

/* ---------------------------------------------------------- add to cart */

html:root .woocommerce div.product form.cart {
	display:     flex;
	align-items: stretch;
	gap:         12px;
	flex-wrap:   wrap;
	margin:      0 0 24px;
}

html:root .woocommerce div.product form.cart .quantity input.qty {
	width:         84px;
	padding:       14px 8px;
	border:        1px solid rgb(140 113 106);
	border-radius: 8px;
	text-align:    center;
	font-family:   Inter;
	font-size:     16px;
}

html:root .woocommerce div.product form.cart button.single_add_to_cart_button {
	flex:            1 1 220px;
	padding:         14px 24px;
	border:          0;
	border-radius:   8px;
	background:      rgb(170 55 18);
	color:           #fff;
	font-family:     Montserrat;
	font-size:       18px;
	line-height:     28px;
	font-weight:     700;
	text-align:      center;
	cursor:          pointer;
	transition:      background-color .15s;
}

html:root .woocommerce div.product form.cart button.single_add_to_cart_button:hover {
	background: rgb(134 34 0);
}

html:root .woocommerce div.product .product_meta {
	padding-top: 16px;
	border-top:  1px solid rgb(224 191 183);
	font-family: Inter;
	font-size:   14px;
	line-height: 20px;
	color:       rgb(82 68 65);
}

/* ------------------------------------------------------------------ tabs */

/*
 * The course page's tab bar: a row of labels over a hairline, the active one carrying the
 * ROAR-orange underline. WooCommerce ships this as a bordered list with rounded tab "chips",
 * which belongs to no other page on this site.
 */
html:root .woocommerce div.product .woocommerce-tabs {
	margin-top: 48px;
}

html:root .woocommerce div.product .wc-tabs {
	display:       flex;
	gap:           24px;
	margin:        0 0 24px;
	padding:       0;
	list-style:    none;
	border-bottom: 1px solid rgb(224 191 183);
}

html:root .woocommerce div.product .wc-tabs::before,
html:root .woocommerce div.product .wc-tabs li::before,
html:root .woocommerce div.product .wc-tabs li::after {
	content: none;   /* WooCommerce draws chip corners with pseudo-elements */
}

html:root .woocommerce div.product .wc-tabs li {
	margin:        0;
	padding:       0;
	background:    none;
	border:        0;
	border-radius: 0;
}

html:root .woocommerce div.product .wc-tabs li a {
	display:         block;
	padding:         12px 0;
	border-bottom:   2px solid transparent;
	font-family:     Inter;
	font-size:       14px;
	line-height:     20px;
	font-weight:     600;
	letter-spacing:  0.7px;
	color:           rgb(82 68 65);
	text-decoration: none;
}

html:root .woocommerce div.product .wc-tabs li.active a,
html:root .woocommerce div.product .wc-tabs li a:hover {
	color:               rgb(170 55 18);
	border-bottom-color: rgb(170 55 18);
}

html:root .woocommerce div.product .woocommerce-Tabs-panel h2 {
	font-family: Montserrat;
	font-size:   24px;
	line-height: 32px;
	font-weight: 700;
	color:       rgb(25 28 29);
	margin:      0 0 12px;
}

html:root .woocommerce div.product .woocommerce-Tabs-panel p {
	font-family: Inter;
	font-size:   16px;
	line-height: 24px;
	color:       rgb(82 68 65);
}

/* --------------------------------------------------------------- mobile */

@media ( max-width: 767px ) {
	html:root .woocommerce div.product .woocommerce-product-gallery,
	html:root .woocommerce div.product .summary {
		float:         none;
		width:         100%;
		margin-bottom: 24px;
	}

	html:root .woocommerce div.product .product_title {
		font-size:   26px;
		line-height: 34px;
	}

	/* A tab bar that does not fit becomes a row you can swipe, not a row that overflows. */
	html:root .woocommerce div.product .wc-tabs {
		overflow-x: auto;
		gap:        16px;
	}

	html:root .woocommerce div.product .wc-tabs li a {
		white-space: nowrap;
	}

	html:root .woocommerce div.product form.cart button.single_add_to_cart_button {
		flex: 1 1 100%;
	}
}

/* ---------------------------------------------------------------------------
 * The cart: WooCommerce's classic output in the design's two-column layout
 *
 * cart.html puts the items on the left at 8 columns and the Order Summary on
 * the right at 4, sticky, with the "Need advice first?" card beneath it. The
 * classic shortcode emits those two as siblings inside `.woocommerce` — a form
 * and a `.cart-collaterals` — which is exactly why it was chosen over the block
 * cart: siblings can be placed, a single client-rendered column cannot.
 *
 * The shortcode's own Bricks wrapper spans all 12 columns and becomes the grid,
 * so WooCommerce's two halves land in the design's proportions without either
 * of them knowing about the other.
 *
 * Below `lg` everything stacks, which is the design's `grid-cols-1`.
 * ------------------------------------------------------------------------- */
html:root .roar-cart-layout {
	display: grid;
	gap:     24px;
}

/*
 * `min-width: 0` on every grid item, at every width. This is the whole mobile fix.
 *
 * A grid item's automatic minimum size is its min-content width, and that minimum BEATS
 * `max-width: 100%` — so the WooCommerce wrapper sat at 1100px inside a 338px column on a
 * 370px phone, and the page needed 1116px of horizontal scroll. The card-stack rules further
 * down were all working correctly; they were just being applied inside a box that could not
 * shrink, which is why the symptom looked like the mobile styles had not loaded at all.
 *
 * The same applies to the table: `table-layout: fixed` sizes columns but does not stop a table
 * asserting a min-content width to its parent.
 */
html:root .roar-cart-layout > *,
html:root .roar-cart-layout .woocommerce,
html:root .roar-cart-layout .woocommerce-cart-form,
html:root .roar-cart-layout .shop_table.cart,
html:root .roar-cart-layout .cart-collaterals {
	min-width: 0;
	max-width: 100%;
}

@media ( min-width: 1024px ) {
	html:root .roar-cart-layout {
		/*
		 * minmax(0, …), not a bare `2fr 1fr`.
		 *
		 * An `fr` track has an automatic minimum of min-content, so the items table — which is
		 * six columns of product name, price, quantity and subtotal — set the floor for the
		 * first track and took 1100px of a 1232px row, leaving the Order Summary 132px wide with
		 * "Cart totals" wrapping onto two lines and the checkout button squeezed to 48px.
		 * minmax(0, …) removes that floor so the ratio is the ratio.
		 */
		grid-template-columns: minmax( 0, 2fr ) minmax( 0, 1fr );   /* the design's 8 / 4 of twelve */
		gap:                   32px;
		align-items:           start;
	}

	/*
	 * `display: contents` on both wrappers is what makes this work.
	 *
	 * WooCommerce emits the items form and the totals panel as siblings inside a `.woocommerce`
	 * div, which itself sits inside the Bricks shortcode's own div. Two nested wrappers means
	 * the grid sees ONE child and the design's split is impossible. Removing both from the box
	 * tree promotes the form and the totals to grid items of the layout, alongside the advice
	 * card — so all three can be placed.
	 *
	 * A first attempt made `.woocommerce` itself the grid instead. That put the form and totals
	 * side by side but left the advice card outside, in the parent grid, where it overlapped the
	 * table; and the tracks came out 1100px/215px rather than 2:1, because the form's intrinsic
	 * width won against an `fr` it was not actually a child of.
	 */
	html:root .roar-cart-woo,
	html:root .roar-cart-woo > .woocommerce {
		display: contents;
	}

	html:root .roar-cart-layout form.woocommerce-cart-form {
		grid-column: 1;
		grid-row:    1 / span 2;
		min-width:   0;   /* or a long product name forces the column wider than its track */
	}

	html:root .roar-cart-layout .cart-collaterals {
		grid-column: 2;
		grid-row:    1;
		min-width:   0;
	}

	html:root .roar-cart-advice {
		grid-column: 2;
		grid-row:    2;
	}

	/* Notices and the empty-cart message have no column to sit in — give them the full width. */
	html:root .roar-cart-layout .woocommerce-notices-wrapper,
	html:root .roar-cart-layout .cart-empty,
	html:root .roar-cart-layout .return-to-shop {
		grid-column: 1 / -1;
	}
}

/*
 * WooCommerce's own float layout, undone.
 *
 * The classic cart is styled for a pre-grid world: `.cart-collaterals` floats right at 48% and
 * `.cart_totals` floats right at 48% of THAT. Inside a grid column those percentages are of the
 * column, so the Order Summary rendered at half the width it had been given — its heading
 * wrapped, the totals overflowed their cells, and "Proceed to checkout" broke across three
 * lines. The floats also take the panel out of normal flow, which a grid item should not be.
 */
html:root .roar-cart-layout .cart-collaterals,
html:root .roar-cart-layout .cart-collaterals .cart_totals,
html:root .roar-cart-layout .woocommerce-cart-form {
	float:     none;
	width:     100%;
	max-width: 100%;
}

html:root .roar-cart-layout .cart-collaterals::after,
html:root .roar-cart-layout .woocommerce-cart-form::after {
	content: none;   /* the clearfix that went with the floats */
}

/* --------------------------------------------------------- the items table */

html:root .roar-cart-woo .shop_table.cart {
	width:           100%;
	border-collapse: collapse;
	background:      rgb(255 255 255);
	border:          1px solid rgb(224 191 183);   /* outline-variant */
	border-radius:   12px;
	overflow:        hidden;

	/*
	 * `fixed`, so the table takes the width it is given rather than the width its longest
	 * product name would like. With `auto` the table refuses to go below its min-content and
	 * pushes the whole grid out of proportion — the column widths below are what it uses
	 * instead, and they add up to something that fits.
	 */
	table-layout: fixed;
}

/* Product name takes whatever is left; the rest are sized to their content. */
@media ( min-width: 768px ) {
	html:root .roar-cart-woo .shop_table.cart .product-remove    { width: 44px; }
	html:root .roar-cart-woo .shop_table.cart .product-thumbnail { width: 96px; }
	html:root .roar-cart-woo .shop_table.cart .product-price     { width: 110px; }
	html:root .roar-cart-woo .shop_table.cart .product-quantity  { width: 132px; }
	html:root .roar-cart-woo .shop_table.cart .product-subtotal  { width: 120px; }
}

html:root .roar-cart-woo .shop_table.cart td.product-name {
	overflow-wrap: anywhere;   /* a long product name wraps rather than overflowing its cell */
}

/*
 * The quantity stepper has to stay inside its column.
 *
 * Bricks styles `.quantity` as an inline-flex group with its own minimum widths, which under
 * `table-layout: fixed` overflowed the 132px cell and painted the plus button on top of the
 * Subtotal figure next to it — "$2,995.00" with a stepper drawn through it.
 */
html:root .roar-cart-woo .shop_table.cart td.product-quantity {
	overflow: hidden;
}

html:root .roar-cart-woo .shop_table.cart .quantity {
	display:   flex;
	max-width: 100%;
}

html:root .roar-cart-woo .shop_table.cart .quantity input.qty {
	min-width:  0;
	width:      100%;
	text-align: center;
}

html:root .roar-cart-woo .shop_table.cart .quantity button,
html:root .roar-cart-woo .shop_table.cart .quantity .qty-button {
	flex: 0 0 auto;
}

html:root .roar-cart-woo .shop_table.cart th {
	padding:        16px;
	text-align:     left;
	background:     rgb(247 243 242);              /* surface-container-low */
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    700;
	letter-spacing: 0.7px;
	color:          rgb(25 28 29);
}

html:root .roar-cart-woo .shop_table.cart td {
	padding:       16px;
	border-top:    1px solid rgb(224 191 183);
	font-family:   Inter;
	font-size:     16px;
	line-height:   24px;
	color:         rgb(82 68 65);
	vertical-align: middle;
}

html:root .roar-cart-woo .shop_table.cart td.product-name a {
	color:       rgb(25 28 29);
	font-weight: 700;
}

html:root .roar-cart-woo .shop_table.cart td.product-name a:hover {
	color: rgb(170 55 18);
}

html:root .roar-cart-woo .shop_table.cart .product-thumbnail img {
	width:         72px;
	height:        72px;
	object-fit:    contain;
	border-radius: 8px;
	background:    #fff;
}

/* -------------------------------------------------------- the totals panel */

html:root .roar-cart-woo .cart_totals {
	background:    #fff;
	padding:       24px;
	border:        1px solid rgb(224 191 183);
	border-radius: 12px;
	box-shadow:    0 4px 6px -1px rgb(0 0 0 / 0.1);
}

html:root .roar-cart-woo .cart_totals h2 {
	font-family: Montserrat;
	font-size:   24px;
	line-height: 32px;
	font-weight: 700;
	color:       rgb(25 28 29);
	margin:      0 0 16px;
}

html:root .roar-cart-woo .cart_totals table {
	width:           100%;
	border-collapse: collapse;
	margin-bottom:   16px;
}

html:root .roar-cart-woo .cart_totals th,
html:root .roar-cart-woo .cart_totals td {
	padding:     8px 0;
	text-align:  left;
	font-family: Inter;
	font-size:   16px;
	line-height: 24px;
}

html:root .roar-cart-woo .cart_totals th {
	color:       rgb(82 68 65);
	font-weight: 400;
}

html:root .roar-cart-woo .cart_totals td {
	text-align:  right;
	color:       rgb(25 28 29);
	font-weight: 700;
}

html:root .roar-cart-woo .cart_totals .order-total td {
	font-size:   20px;
	line-height: 28px;
}

/* ------------------------------------------------------------- the buttons */

/*
 * Proceed to Checkout is the design's primary button, full width at the foot of the summary —
 * the same shape and weight as "Request This Order" in cart.html, doing the thing ROAR chose to
 * keep instead.
 */
html:root .roar-cart-woo .wc-proceed-to-checkout a.checkout-button {
	display:         block;
	width:           100%;
	padding:         14px 24px;
	border-radius:   8px;
	background:      rgb(170 55 18);
	color:           #fff;
	font-family:     Montserrat;
	font-size:       18px;
	line-height:     28px;
	font-weight:     700;
	text-align:      center;
	text-decoration: none;
	transition:      background-color .15s;
}

html:root .roar-cart-woo .wc-proceed-to-checkout a.checkout-button:hover {
	background: rgb(134 34 0);
}

/* Update cart, Apply coupon: secondary, so they cannot compete with checkout. */
html:root .roar-cart-woo button[name="update_cart"],
html:root .roar-cart-woo button[name="apply_coupon"] {
	padding:       10px 18px;
	border:        1px solid rgb(140 113 106);
	border-radius: 8px;
	background:    transparent;
	color:         rgb(25 28 29);
	font-family:   Inter;
	font-size:     14px;
	line-height:   20px;
	font-weight:   600;
}

html:root .roar-cart-woo button[name="update_cart"]:hover:not( :disabled ),
html:root .roar-cart-woo button[name="apply_coupon"]:hover {
	border-color: rgb(170 55 18);
	color:        rgb(170 55 18);
}

html:root .roar-cart-woo .coupon input[type="text"] {
	padding:       10px 12px;
	border:        1px solid rgb(140 113 106);
	border-radius: 8px;
	margin-right:  8px;
}

/* ------------------------------------------------------------ small screens */

/*
 * The items table becomes a stack of cards. A six-column table on a 390px phone either
 * overflows horizontally or squeezes every cell to unreadable — this is the design's own
 * "complex tables reflow to card stacks on mobile" rule from the design system.
 */
@media ( max-width: 767px ) {
	html:root .roar-cart-woo .shop_table.cart thead {
		display: none;
	}

	html:root .roar-cart-woo .shop_table.cart,
	html:root .roar-cart-woo .shop_table.cart tbody,
	html:root .roar-cart-woo .shop_table.cart tr,
	html:root .roar-cart-woo .shop_table.cart td {
		display: block;
		width:   100%;
	}

	html:root .roar-cart-woo .shop_table.cart tr {
		padding:       16px;
		border-top:    1px solid rgb(224 191 183);
		position:      relative;
	}

	html:root .roar-cart-woo .shop_table.cart td {
		padding:    4px 0;
		border-top: 0;
		text-align: left;
	}

	/*
	 * With the header row gone the cells lose their meaning, so each carries its own label.
	 * WooCommerce puts the column name in data-title for exactly this.
	 */
	/*
	 * `[data-title]` in the selector, not just in the content.
	 *
	 * Cells WooCommerce does not label — the actions row holding Update cart and the coupon —
	 * have no data-title, so `attr(data-title)` resolved to nothing and the cell rendered a
	 * bare ": " floating to the left of the button. Requiring the attribute means only labelled
	 * cells get a label.
	 */
	html:root .roar-cart-woo .shop_table.cart td[ data-title ]::before {
		content:       attr( data-title );
		display:       block;
		margin-bottom: 4px;
		font-family:   Inter;
		font-size:     12px;
		line-height:   16px;
		font-weight:   700;
		letter-spacing: 0.5px;
		text-transform: uppercase;
		color:         rgb(82 68 65);
	}

	html:root .roar-cart-woo .shop_table.cart td.product-thumbnail::before,
	html:root .roar-cart-woo .shop_table.cart td.product-remove::before {
		content: none;
	}

	/* Room between the stacked fields — the whole point of the card layout. */
	html:root .roar-cart-woo .shop_table.cart td {
		padding-block: 12px;
	}

	html:root .roar-cart-woo .shop_table.cart td + td {
		border-top: 1px solid rgb(240 236 235);
	}

	html:root .roar-cart-woo .shop_table.cart tr {
		padding: 20px 16px;
	}

	/*
	 * The product name is a `<th>`, not a `<td>`.
	 *
	 * Which means it kept the shaded background meant for the table's header row, and appeared
	 * as one field highlighted in a card where nothing else was — the grey box in ROAR's
	 * screenshot. A first fix targeted `td.product-name` and matched nothing at all.
	 *
	 * Every other cell selector in this block deliberately says `td, th` for the same reason.
	 */
	html:root .roar-cart-woo .shop_table.cart tbody th {
		display:        block;
		width:          100%;
		padding:        12px 0;
		background:     none;
		border-top:     1px solid rgb(240 236 235);
		text-align:     left;
		font-family:    Inter;
		font-size:      16px;
		line-height:    24px;
		font-weight:    700;
		letter-spacing: normal;
		color:          rgb(25 28 29);
	}

	html:root .roar-cart-woo .shop_table.cart tbody th[ data-title ]::before {
		content:        attr( data-title );
		display:        block;
		margin-bottom:  4px;
		font-size:      12px;
		line-height:    16px;
		font-weight:    700;
		letter-spacing: 0.5px;
		text-transform: uppercase;
		color:          rgb(82 68 65);
	}

	/* The first cell in a card has nothing above it to be divided from. */
	html:root .roar-cart-woo .shop_table.cart tbody tr > :first-child,
	html:root .roar-cart-woo .shop_table.cart tbody td.product-thumbnail + th,
	html:root .roar-cart-woo .shop_table.cart tbody td.product-thumbnail {
		border-top: 0;
	}

	html:root .roar-cart-woo .shop_table.cart td.product-thumbnail {
		padding-bottom: 4px;
	}

	html:root .roar-cart-woo .shop_table.cart td.product-thumbnail img {
		width:  88px;
		height: 88px;
	}

	/* The actions row: full-width controls, stacked, with space between them. */
	html:root .roar-cart-woo .shop_table.cart td.actions {
		display:        flex;
		flex-direction: column;
		gap:            12px;
		padding-block:  16px;
	}

	html:root .roar-cart-woo .shop_table.cart td.actions .coupon {
		display:        flex;
		flex-direction: column;
		gap:            12px;
		width:          100%;
	}

	html:root .roar-cart-woo .shop_table.cart td.actions .coupon input[type="text"],
	html:root .roar-cart-woo .shop_table.cart td.actions button {
		width:        100%;
		margin-right: 0;
	}

	html:root .roar-cart-woo .shop_table.cart td.product-remove {
		position: absolute;
		top:      12px;
		right:    12px;
		width:    auto;
	}
}

/*
 * `alignwide` breaks the cart out of the content column with a NEGATIVE right margin, and it
 * beat the `margin-inline: auto` above — the whole block ended up sitting 90px right of centre.
 *
 * Everything inside it was centred correctly relative to the block, so the sad face and the
 * empty message measured perfectly centred while visibly sitting off to one side. That is what
 * ROAR was seeing, and it is why the first attempt at centring the icon changed nothing: the
 * icon was never the thing that was off.
 *
 * The block now fills the content column rather than escaping it, which is where every other
 * page on the site puts its content.
 */
html:root body.woocommerce-cart .wp-block-woocommerce-cart,
html:root body.woocommerce-checkout .wp-block-woocommerce-checkout {
	max-width:     100%;
	margin-inline: auto;
}

@media ( min-width: 768px ) {
	html:root .woocommerce div.product,
	html:root .wp-block-woocommerce-cart,
	html:root .wp-block-woocommerce-checkout,
	html:root .woocommerce-notices-wrapper,
	html:root .woocommerce-breadcrumb {
		padding-inline: 24px;
	}
}

/* The product gallery should not be taller than the phone it is on. */
@media ( max-width: 767px ) {
	html:root .woocommerce div.product .woocommerce-product-gallery img {
		max-height: 60vh;
		width:      auto;
		margin:     0 auto;
	}
}

/* ---------------------------------------------------------------------------
 * The homepage hero fits the screen
 *
 * ROAR asked for the hero photo and its heading, copy and buttons to all be
 * visible at first glance, without scrolling — desktop and tablet only.
 *
 * The design sizes the hero by minimum height alone: `min-h-[560px]
 * md:min-h-[640px] 2xl:min-h-[780px]`. Those are floors, not ceilings, so on a
 * laptop the hero simply grows past the fold — 780px of hero under a 97px
 * sticky header is 877px of page before the trust bar, against roughly 680px of
 * usable height on a 1080p laptop at 125% scaling. The buttons and the trust
 * bar were both below the fold.
 *
 * Height is tied to the viewport instead, less the header, which is the same
 * `calc(100vh - 96px)` idiom the design already uses for its mobile menu panel.
 *
 * The floor and ceiling both matter. Without `min-height` a short window would
 * crush the hero until the copy collided with the buttons; without max-height a
 * tall monitor would stretch one photo over 1200px. 780px is the design's own
 * largest value, so the hero never exceeds what the design asked for.
 *
 * Untouched below 768px. On a phone the hero is a stacked column of heading,
 * paragraph and two full-width buttons — forcing that into 100vh would shrink
 * the photo to a strip, and ROAR explicitly excluded mobile.
 * ------------------------------------------------------------------------- */
/*
 * Scoped to `body.home` — WordPress' own class for the front page — so it is the homepage hero
 * and nothing else. Every page has a `#main-content` whose first section carries an h1, so a
 * selector keyed on structure alone would have capped the course, shop and contact heroes too.
 *
 * `#main-content` rather than `#brx-content`: Bricks nests an extra div between the two, and a
 * `>` combinator on the outer one silently matches nothing.
 */
@media ( min-width: 768px ) {
	html:root body.home #main-content > section:first-of-type {
		/*
		 * 96px header + 69px trust strip.
		 *
		 * ROAR chose to have the strip land on screen under the hero rather than exactly at the
		 * fold — it is what their reference shows, and a band of page below the hero is also
		 * what tells a visitor there is more to scroll to.
		 *
		 * The two numbers are separate on purpose: they are two different elements, and someone
		 * changing the header height should not have to work out what a combined 165 was made of.
		 */
		height:     calc( 100vh - 96px - 69px );
		min-height: 480px;
		max-height: 780px;
	}
}

/* ---------------------------------------------------------------------------
 * The course archive's filter row: search, category and sort on ONE line
 *
 * The approved design already lays these out as a single row from `lg:` up —
 * `flex flex-col lg:flex-row` on the bar, with the two selects side by side in
 * their own `flex flex-wrap` group. All of that markup is present and correct
 * on the built page; the row still broke into three stacked controls.
 *
 * The cause is Bricks, which styles bare form controls:
 *
 *     .input, input:not([type=submit]), select, textarea { … width: 100% }
 *
 * The static design never had that — Tailwind's preflight leaves a <select> at
 * its intrinsic width — so each select expanded to fill the group and wrapped
 * onto its own line. Nothing in the markup hinted at it: the classes, the flex
 * direction and the wrap setting all measured exactly as designed.
 *
 * Scoped to these two ids, not to `select` generally. The enquiry modal's
 * Location select is `w-full` in the design and MUST keep Bricks' behaviour, so
 * a blanket reset would fix this row and break that one.
 * ------------------------------------------------------------------------- */
html:root #filter-category,
html:root #filter-sort {
	width: auto;
}

/* ---------------------------------------------------------------------------
 * Enquiry popup
 *
 * Bricks supplies the overlay, the backdrop and the dialog behaviour; the card
 * inside is ours. Bricks' own content wrapper brings a background, padding and a
 * width of its own, which would sit as a second card behind the real one — so it
 * is neutralised and the design's card does the work.
 *
 * The form is the same situation as the course sidebar form: Bricks generates
 * .form-group / .label / input markup with no per-field class control, so the
 * design's utility stack is restated here against Bricks' own selectors. Values
 * are copied from the utilities they replace, not re-picked.
 * ------------------------------------------------------------------------- */
html:root .brx-popup .brx-popup-content {
	background:    transparent;
	padding:       0;
	border:        0;
	border-radius: 0;
	/*
	 * 672px, NOT 42rem — even though the design's max-w-2xl is literally 42rem.
	 *
	 * Bricks sets `html { font-size: 62.5% }`, so 1rem is 10px here, not 16px. Written as
	 * 42rem this resolved to 420px and the dialog rendered a third narrower than the approved
	 * design: two columns of fields squeezed into 405px, the subtitle wrapping onto two lines
	 * and the whole form needing a scrollbar. ROAR reported it as the form being crowded.
	 *
	 * The generated utilities are rebased for this by build/make-utilities-css.js. This block
	 * is hand-written against Bricks' own selectors, so it was never put through that and has
	 * to carry px directly. Anything added to this file in rem has the same trap waiting.
	 */
	max-width:     672px;          /* the design's max-w-2xl, rebased from 42rem */
	width:         100%;

	/*
	 * The OVERLAY scrolls, not the card — which is what the design does:
	 * `fixed inset-0 overflow-y-auto` around a card carrying `my-md`.
	 *
	 * Bricks instead centres a fixed-height box and scrolls the card's own contents, and two
	 * things went wrong with that. The card is taller than the viewport, and a flex-CENTRED
	 * item that overflows gets clipped at the top rather than pushed down — so it sat 14px
	 * above the screen with its heading cut off and no way to scroll up to it. Separately, the
	 * scrollbar lived inside the card and took 15px off the content width, leaving the fields
	 * 292px wide against the design's 300.
	 *
	 * Handing the scroll to the overlay fixes both at once. `flex-start` is the design's
	 * `items-start`, and is also what stops the clipping from coming back on a long form.
	 */
	margin:     24px auto;
	overflow:   visible;
}

/*
 * `justify-content`, not `align-items` — .brx-popup is a flex COLUMN.
 *
 * In a column the axes swap: justify-content is the vertical one. Bricks sets it to `center`,
 * and a centred flex item taller than its container overflows equally in both directions with
 * the top half unreachable — the card sat 75px above the viewport with its heading cut off,
 * and scrolling could not bring it back because the overflow was above the scroll origin.
 *
 * `flex-start` is the design's `items-start`. `align-items: center` then does the horizontal
 * centring that `align-items: flex-start` had been quietly undoing.
 */
html:root .brx-popup {
	overflow-y:      auto;
	justify-content: flex-start;
	align-items:     center;
}

/*
 * The close button sits on the card, not in a chip. Bricks gives every button a background;
 * the design leaves it transparent and only fills it on hover, which is what the
 * `hover:bg-surface-container-high` class in the markup is for — it was being pre-empted by a
 * background that never went away, so the button read as permanently hovered.
 */
html:root .brx-popup [data-enquiry-close],
html:root .brx-popup button[aria-label^="Close"] {
	background: transparent;
	border:     0;
}

/*
 * The form is the design's grid, not Bricks' wrapping flexbox.
 *
 * The design is `grid grid-cols-1 md:grid-cols-2 gap-md` — two equal columns, 24px apart, 24px
 * between rows. Bricks renders a `display: flex; flex-wrap: wrap` with no gap at all and lays
 * the fields out by letting each .form-group size itself to roughly half the row. The result
 * measured: a column gap of ZERO — First Name and Last Name touching down their shared edge —
 * and a row pitch of 110px against the design's 98, from a 16px margin-bottom stacking on top
 * of the space the design already allows. ROAR reported it as the arrangement being wrong.
 *
 * Grid rather than flex-with-a-gap on purpose. Under flex the two halves would have to be
 * `calc(50% - 12px)` to leave room for the gap, which means restating a width Bricks is already
 * computing and getting it wrong the moment anyone changes a field's width in the builder.
 * Grid tracks take the gap out of the row before sizing the columns, so nothing needs a width.
 *
 * The full-width rows are selected by FIELD NAME, not by :nth-child. Position-based selectors
 * would silently reassign themselves the first time ROAR reorders a field in the builder, and
 * the failure would be a subtly wrong layout rather than an error.
 */
html:root .roar-enquiry-modal-form {
	display:               grid;
	grid-template-columns: 1fr;
	gap:                   24px;                /* the design's gap-md */
}

/* The design's md: breakpoint, where one column becomes two. */
@media ( min-width: 768px ) {
	html:root .roar-enquiry-modal-form {
		grid-template-columns: 1fr 1fr;
	}

	html:root .roar-enquiry-modal-form .form-group:has( [name="course"] ),
	html:root .roar-enquiry-modal-form .form-group:has( [name="message"] ),
	html:root .roar-enquiry-modal-form .submit-button-wrapper {
		grid-column: 1 / -1;
	}
}

/*
 * No width is set here on purpose. Bricks emits `#brxe-popfrm .form-group:nth-child(n)
 * { width: 100% }` at (1,2,0), which nothing in this file can outrank without !important —
 * so the fields are all set to width 100 in migration/wp/build-enquiry-popup.php instead, and
 * 100% of a grid track is exactly "fill the track". Overriding it here would be a fight this
 * file cannot win; the note in that script explains why the setting is what it is.
 *
 * padding-bottom rather than margin: Bricks' own `.form-group { padding: 0 0 20px }` is what
 * puts 20px under every field, which stacked on top of the grid's 24px row gap and made the
 * rows 110px apart instead of 98.
 */
html:root .roar-enquiry-modal-form .form-group {
	margin-bottom:  0;
	padding-bottom: 0;   /* the grid's row gap is the only vertical spacing */
}

html:root .roar-enquiry-modal-form label {
	display:       block;
	margin-bottom: 4px;
	font-family:   Inter;
	font-size:     14px;
	line-height:   20px;
	font-weight:   600;
	letter-spacing: .05em;
	color:         rgb(25 28 29);

	/*
	 * Bricks shouts every form label: `:where(.brxe-form) label { text-transform: uppercase }`.
	 * The design writes them in title case — "First Name", not "FIRST NAME". Restated here
	 * because `:where()` has zero specificity, so Bricks' rule is only (0,0,1) and everything
	 * this block sets already outranks it; text-transform simply was not among the properties
	 * being set, so the shouting came through unopposed.
	 */
	text-transform: none;
}

/*
 * The design's required markers: a red asterisk after the label text.
 *
 * Bricks has no setting for this — the fields carry the real `required` attribute and validate
 * correctly, but nothing said so on screen, which leaves someone to discover which fields are
 * mandatory by submitting and being told off.
 *
 * Driven off `:has([required])` so it reads the actual attribute rather than a hard-coded list
 * of field names. If ROAR makes Phone required in the builder later, the asterisk follows on
 * its own; if this were a list, it would quietly lie.
 *
 * aria-hidden is not available on generated content, but nothing is lost: the `required`
 * attribute is what a screen reader announces, and it is already there. The asterisk is a
 * visual convention for sighted users and is purely additive.
 */
html:root .roar-enquiry-modal-form .form-group:has( [required] ) > label::after {
	content:     " *";
	color:       rgb(186 26 26);   /* the design's text-error */
	font-weight: 700;
}

html:root .roar-enquiry-modal-form .form-group input,
html:root .roar-enquiry-modal-form .form-group select,
html:root .roar-enquiry-modal-form .form-group textarea {
	width:         100%;
	padding:       12px;
	border:        1px solid rgb(140 113 106);
	border-radius: 8px;
	background:    #fff;
	color:         rgb(25 28 29);
	font-family:   Inter;
	font-size:     16px;
	line-height:   24px;
	font-weight:   400;
}

/*
 * The Course field is filled in for the visitor, and the design shades it to say so —
 * bg-surface-container-low, a step darker than the fields they have to type into themselves.
 * Keyed on the field name so it follows the field rather than its position in the form.
 */
html:root .roar-enquiry-modal-form .form-group [name="course"] {
	background: rgb(247 243 242);   /* the design's surface-container-low */
}

/* The note under it, inserted by assets/js/enquiry-modal.js. The design's font-caption. */
html:root .roar-enquiry-modal-form .roar-course-hint {
	margin:      4px 0 0;
	font-family: Inter;
	font-size:   12px;
	line-height: 16px;
	font-weight: 400;
	color:       rgb(82 68 65);     /* the design's on-surface-variant */
}

/* The design's focus:border-primary focus:ring-1, as a real outline so it
   survives forced-colors mode, where box-shadow rings disappear entirely. */
html:root .roar-enquiry-modal-form .form-group :is(input, select, textarea):focus {
	outline:        2px solid rgb(170 55 18);
	outline-offset: 0;
	border-color:   transparent;
}

html:root .roar-enquiry-modal-form button[type="submit"] {
	width:          100%;
	padding:        12px 24px;
	border:         0;
	border-radius:  8px;
	background:     rgb(170 55 18);
	color:          #fff;
	font-family:    Inter;
	font-size:      14px;
	line-height:    20px;
	font-weight:    700;
	letter-spacing: .05em;
	transition:     background-color .15s;
}

html:root .roar-enquiry-modal-form button[type="submit"]:hover,
html:root .roar-enquiry-modal-form button[type="submit"]:focus-visible {
	background: rgb(134 34 0);
}

/* ---------------------------------------------------------------------------
 * Do not lazy-load a CSS gradient
 *
 * Bricks marks every nestable element `bricks-lazy-hidden` and suppresses its
 * background with `background-image: none !important` until its
 * IntersectionObserver reveals it. That is right for a background photograph
 * and wrong for a gradient: there is nothing to fetch, so the only effect is a
 * window where the gradient is missing.
 *
 * On the hero that window is the one that matters. The headline is white and
 * sits over a bright photograph; the two gradient overlays are what make it
 * readable. Until the observer fires, the page renders white text on daylight —
 * and if scripts are slow or blocked it never recovers.
 *
 * !important is required to beat Bricks' own !important, and the attribute
 * selector plus html:root (0,2,1) outranks its single class (0,1,0). Only the
 * two directions the design actually uses are restated, so this cannot quietly
 * cover a gradient nobody has looked at.
 * ------------------------------------------------------------------------- */
html:root [class*="bg-gradient-to-r"] {
	background-image: linear-gradient(to right, var(--tw-gradient-stops)) !important;
}

html:root [class*="bg-gradient-to-t"] {
	background-image: linear-gradient(to top, var(--tw-gradient-stops)) !important;
}

/* ---------------------------------------------------------------------------
 * Nav dropdown
 *
 * Bricks' submenu ships its own look — a dark slate panel with white text, no
 * border, no radius and no padding — which belongs to Bricks' default theme and
 * not to this one. The design's dropdown is a white card: bordered, rounded,
 * lifted on a shadow, with dark text that turns primary on hover.
 *
 * The nav menu is a native Bricks element on purpose, so ROAR can manage the
 * menu from Appearance without touching a template. That means its styling
 * cannot come from utility classes in markup we control — it has to be stated
 * here against Bricks' own selectors, the same bargain as the enquiry form.
 *
 * Values are the design's tokens, copied from the utilities they replace:
 *
 *   panel  w-64 bg-surface-container-lowest border border-outline-variant
 *          rounded shadow-lg py-base
 *   item   px-md py-sm text-on-surface font-body-md
 *          hover:bg-surface-container-high hover:text-primary
 * ------------------------------------------------------------------------- */
html:root .bricks-nav-menu .sub-menu {
	min-width:      256px;
	background:     rgb(255 255 255);
	border:         1px solid rgb(224 191 183);
	border-radius:  8px;
	padding:        8px 0;
	box-shadow:     0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -4px rgba(0, 0, 0, .1);
}

html:root .bricks-nav-menu .sub-menu > li > a,
html:root .bricks-nav-menu .sub-menu > li > .brx-submenu-toggle > a {
	display:     block;
	padding:     12px 24px;
	background:  transparent;
	color:       rgb(25 28 29);
	font-family: Inter;
	font-size:   16px;
	line-height: 24px;
	transition:  background-color .15s, color .15s;
}

html:root .bricks-nav-menu .sub-menu > li > a:hover,
html:root .bricks-nav-menu .sub-menu > li > a:focus-visible,
html:root .bricks-nav-menu .sub-menu > li > .brx-submenu-toggle > a:hover {
	background: rgb(231 232 233);
	color:      rgb(170 55 18);
}

/* ---------------------------------------------------------------------------
 * Make the design's borders exist
 *
 * Tailwind's border utilities set a WIDTH and a COLOUR and nothing else. They
 * rely on preflight for the style:
 *
 *     *, ::before, ::after { border-width: 0; border-style: solid }
 *
 * Preflight is excluded here, so border-style stayed at its initial value of
 * `none` — and a border with no style has no width, whatever the utility says.
 * Every `border`, `border-t`, `border-2` and `divide-*` on the site computed to
 * 0px: card outlines, the header's bottom rule, the testimonial dividers, the
 * outlined buttons. All of it silently absent.
 *
 * Scoped to elements that actually ask for a border rather than restated as a
 * universal reset. Preflight's version also zeroes every border on the page,
 * which is exactly what would strip the browser defaults off WooCommerce's and
 * Bricks' own controls — the reason preflight was excluded in the first place.
 * An element carrying a border-* class has opted in; nothing else is touched.
 * ------------------------------------------------------------------------- */
html:root [class~="border"],
html:root [class*="border-"],
html:root [class*="divide-"] > * {
	border-style: solid;
}

/*
 * The other half of that reset — and it is not optional.
 *
 * `border-t` sets border-TOP-width and nothing else. It assumes preflight has already zeroed
 * all four sides, so the three it does not mention stay at 0. Without that, those three fall
 * back to the CSS initial value, `medium` — 3px — and the rule above then gives them a style
 * to render with. The result: every `border-t`, `border-b` and `border-l-4` on the site drew
 * one thin line plus a 3px box around the other three sides, in whatever colour the
 * border-<colour> class set. 33 of them on a single course page.
 *
 * ROAR reported it as "the coloured border on the boxes" — the testimonial name blocks, the
 * card price rows, the unit rows, the Contact info cards. It was never in the design.
 *
 * DELIBERATELY LOWER SPECIFICITY THAN THE UTILITIES — do not add `html:root` to this selector.
 *
 * The width utilities are emitted as `html:root .border-t` (0,2,1). This rule is (0,1,0), so
 * every explicit width still wins and only the undeclared sides collapse to 0. Prefixing it to
 * match would make it (0,2,1) too, and since this file loads after utilities.css it would then
 * win on equal specificity and zero every border on the site — the exact bug this pair of
 * rules exists to fix, reintroduced from the other direction.
 */
[class~="border"],
[class*="border-"],
[class*="divide-"] > * {
	border-width: 0;
}

/* ---------------------------------------------------------------------------
 * Stick the header to the top of the viewport
 *
 * The design's <header> is `sticky top-0 z-50`. Those classes are on the Bricks
 * Section inside Bricks' own #brx-header wrapper — and a sticky element can only
 * travel within its containing block, which is that wrapper. The wrapper is only
 * as tall as the header, so the section had nowhere to stick to and scrolled
 * away with it.
 *
 * Applied to the wrapper instead, which is the element the design's <header>
 * actually corresponds to.
 * ------------------------------------------------------------------------- */
html:root #brx-header {
	position: sticky;
	top:      0;
	z-index:  50;
}

/* ---------------------------------------------------------------------------
 * Header icon sizing
 *
 * The account icon is a Material Symbols glyph that inherits the link's 16px
 * font size; the cart is a Bricks icon element rendering at 27px. Side by side
 * in identical 44x44 targets, one looked half the size of the other.
 *
 * Both are set to 24px — the size the design's header icons use, and the size
 * the rest of the site's inline icons already render at.
 * ------------------------------------------------------------------------- */
html:root #brx-header .material-symbols-outlined,
html:root #brx-header .brxe-woocommerce-mini-cart i,
html:root #brx-header .brxe-woocommerce-mini-cart svg {
	font-size: 24px;
	width:     24px;
	height:    24px;
	line-height: 1;
}

/* ---------------------------------------------------------------------------
 * Current page in the navigation
 *
 * The design marks the tab you are on: primary colour, bold, and a primary
 * underline where the others carry a transparent one. Bricks marks the item with
 * WordPress's standard classes but styles nothing, so every tab looked identical
 * and the nav never told you where you were.
 *
 *   inactive   text-secondary font-medium border-transparent
 *   active     text-primary   font-bold   border-primary
 *
 * current-menu-ancestor and -parent are included so a single course page or a
 * category archive still lights "Our Courses" — see roar_mark_courses_menu_current().
 * ------------------------------------------------------------------------- */
html:root #brx-header .bricks-nav-menu > li.current-menu-item > a,
html:root #brx-header .bricks-nav-menu > li.current-menu-ancestor > a,
html:root #brx-header .bricks-nav-menu > li.current-menu-parent > a,
html:root #brx-header .bricks-nav-menu > li.current-menu-item > .brx-submenu-toggle > a,
html:root #brx-header .bricks-nav-menu > li.current-menu-ancestor > .brx-submenu-toggle > a {
	color:                rgb(170 55 18);
	font-weight:          700;
	border-bottom:        2px solid rgb(170 55 18);
}

/*
 * The underline needs somewhere to sit. Bricks' items have no bottom border, so
 * without a transparent one on every item the active tab would be 2px taller
 * than its neighbours and shunt the row.
 */
html:root #brx-header .bricks-nav-menu > li > a,
html:root #brx-header .bricks-nav-menu > li > .brx-submenu-toggle > a {
	border-bottom: 2px solid transparent;
	transition:    color .15s, border-color .15s;
}

/* The rule above must not reach into the dropdown, which is its own white card. */
html:root #brx-header .bricks-nav-menu .sub-menu > li > a {
	border-bottom: 0;
}

/* ---------------------------------------------------------------------------
 * Footer logo
 *
 * Bricks writes a per-element rule from every image's intrinsic size —
 * `#brxe-chvxln { width: 270px; height: 150px }` — and an id beats the `h-16
 * w-auto` the design puts on it. The mark rendered at 150px tall in a footer
 * column, more than twice its intended size.
 *
 * Same fix as the full-bleed hero images above, and for the same reason: an id
 * cannot be outranked by a class, so this is one of the few places !important
 * is the honest tool. Narrowly scoped to the footer's own logo.
 * ------------------------------------------------------------------------- */
html:root #brx-footer .brxe-image.h-16 {
	height:    64px !important;
	width:     auto !important;
	max-width: 100%;
}

/*
 * .self-start moved to assets/css/layout.css, 2026-08-25, alongside the rule that now depends
 * on it having somewhere to scroll — see that file for both. This file is regenerated by
 * build/fetch-fonts.js and a rule left here would be silently discarded on the next run.
 */
