/**
 * @file
 * CycleIn public chrome: global header, footer and landing-page scaffolding.
 */

:root {
  --cyclein-container: min(100% - (var(--layout-edge-padding) * 2), var(--layout-max-width));
}

/* The core admin toolbar renders on public pages when logged in, as a body-level
   sibling of the theme page wrapper. The theme's global element resets (a → 18px,
   bold + underline; img/svg → display:block) therefore bleed into it and knock
   the toolbar's links and icons out of alignment. Neutralise only those resets
   inside the toolbar so Claro's own styling stands — the theme is not restyling
   the admin UI, just keeping its resets out of it. */
#toolbar-administration a {
  font-size: inherit;
  font-weight: inherit;
  text-decoration: none;
  text-underline-offset: 0;
}

#toolbar-administration img,
#toolbar-administration svg {
  display: inline-block;
  vertical-align: middle;
}

/* Sticky footer: the page fills at least the viewport (min-block-size:100vh set
   in layout.css) and the main region grows to take the slack, so on short pages
   (e.g. the reset-password form) the footer sits at the foot of the viewport
   instead of leaving a band of empty page background beneath it. */
.cyclein-page {
  display: flex;
  flex-direction: column;
}

.cyclein-page__main {
  flex: 1 0 auto;
}

/* ==========================================================================
   Landing pages: flush the constrained main so sections span the viewport.
   ========================================================================== */

main.cyclein-page__main--flush {
  padding-block: 0;
}

main.cyclein-page__main--flush > *,
main.cyclein-page__main--flush .node,
main.cyclein-page__main--flush .node > *,
main.cyclein-page__main--flush .field--name-field-sections,
main.cyclein-page__main--flush .field--name-field-sections > * {
  margin-inline: 0;
  max-inline-size: none;
  padding-inline: 0;
}

/* Shared centred content column used by every section inner wrapper. */
.paragraph--hero__inner,
.paragraph--path-chooser__inner,
.paragraph--feature-split__inner,
.paragraph--video-showcase__inner,
.paragraph--numbered-steps__inner,
.paragraph--benefit-grid__inner,
.paragraph--split-content-image__inner,
.paragraph--callout-banner__inner,
.paragraph--checklist-cta__inner,
.paragraph--pricing-section__inner,
.paragraph--faq-section__inner,
.paragraph--cta-banner__inner {
  inline-size: var(--cyclein-container);
  margin-inline: auto;
}

/* ==========================================================================
   Global header.
   ========================================================================== */

.cyclein-region--header .cyclein-region__inner {
  align-items: center;
  column-gap: var(--space-24);
  display: flex;
  /* Round-8 r12: the header is chrome, not content — Figma draws it as a
     full-width bar whose wordmark sits on the viewport edge padding rather than
     inside the 1200px content column. The previous 1376px chrome container
     centred itself, so above the 1440 breakpoint the gutters grew unbounded
     (~250px at 1920) and the bar read as a floating island. Span the viewport,
     capped at the 1920 breakpoint, with the standard edge padding so the
     wordmark lands at x=32 at every width. */
  inline-size: 100%;
  margin-inline: auto;
  max-inline-size: var(--breakpoint-1920);
  padding-block: var(--space-16);
  padding-inline: var(--layout-edge-padding);
}

/* Round-12 checklist r4: the design's Nav bar is 99px tall on every page (node
   318:14711, height 99, flush to the top of the hero); the bar was 76px, so it
   read "smaller than the design and not flush". Give it the design height on
   desktop; align-items:center keeps the 44px-target controls centred. Scoped to
   >=768px so the mobile two-row header keeps its own geometry. */
@media (min-width: 768px) {
  .cyclein-region--header .cyclein-region__inner {
    min-block-size: 99px;
  }
}

.cyclein-global-header {
  align-items: center;
  column-gap: var(--space-24);
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  row-gap: var(--space-12);
}

/* The block renders its content inside an unclassed container div; collapse it
   so the header controls become direct flex items of the bar. */
.cyclein-global-header > div {
  display: contents;
}

/* Brand link: the "CYCLEIN" text is retained as an accessible fallback but is
   visually replaced by the reconstructed wordmark. The logo is single-colour,
   so an alpha mask painted with currentColor renders it white on the dark
   header (and would recolour anywhere else via `color`). */
.cyclein-global-header__brand {
  align-items: center;
  color: var(--color-brand-white);
  display: inline-flex;
  font-size: 0;
  min-block-size: var(--a11y-min-target);
  text-decoration: none;
}

.cyclein-global-header__brand::before {
  background-color: currentColor;
  block-size: 30px;
  content: "";
  display: block;
  inline-size: 197px;
  -webkit-mask: url("../images/cyclein-logo.svg") left center / contain no-repeat;
  mask: url("../images/cyclein-logo.svg") left center / contain no-repeat;
}

/* Client fb3: every page except the homepage uses the two-colour White & Yellow
   brand logo on the solid dark-teal header (the homepage keeps its transparent
   dark-on-lime treatment below). It is a genuine two-tone SVG, so it is painted
   as a background image, not a single-colour mask. Aspect 1428.71:235.57. */
body:not(.path-frontpage) .cyclein-global-header__brand::before {
  background-color: transparent;
  background-image: url("../images/cyclein-logo-white-yellow.svg");
  background-position: left center;
  background-repeat: no-repeat;
  background-size: contain;
  block-size: 32px;
  inline-size: 194px;
  -webkit-mask: none;
  mask: none;
}

/* Checklist r4: a thin full-width divider rule sits directly beneath the header
   on every page except the homepage (whose header floats transparently over the
   hero), separating the sticky header from the section below. */
body:not(.path-frontpage) .cyclein-region--header {
  border-block-end: 1px solid color-mix(in srgb, var(--color-brand-white) 16%, transparent);
}

.cyclein-global-header__toggle {
  align-items: center;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: var(--radius-8);
  color: var(--color-brand-white);
  display: none;
  font-weight: var(--font-weight-bold);
  justify-content: center;
  margin-inline-start: auto;
  padding: var(--space-8) var(--space-16);
}

.cyclein-global-header__toggle:focus-visible {
  border-radius: var(--a11y-focus-radius-button);
}

.cyclein-global-header__nav {
  margin-inline-start: auto;
}

/* Round-8 r11: Figma spaces the primary-nav items roughly 1.5–1.8× wider than
   the 24px the bar shipped with (measured scale-free against both the wordmark
   and the nav's own cap width), so the links read as separate destinations
   rather than one run-on string. */
/* Round-10 checklist r6: 24px between links, per the design's "Menu items"
   frame (itemSpacing 24). This was 40. */
.cyclein-global-header__nav .menu {
  align-items: center;
  column-gap: var(--space-24);
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Round-10 checklist r6: the design sets the nav links at 20/700 — the C09
   --type-button size — not --type-body (18px), which is why the menu read
   "nhỏ hơn" than the design. */
.cyclein-global-header__nav .menu a {
  color: var(--color-brand-white);
  display: inline-flex;
  align-items: center;
  font-size: var(--type-button-size);
  font-weight: var(--font-weight-bold);
  min-block-size: var(--a11y-min-target);
  text-decoration: none;
}

.cyclein-global-header__nav .menu a:hover {
  color: var(--color-brand-yellow);
}

/* Active section: colour alone must not carry meaning (WCAG 1.4.1), so pair the
   accent colour with a persistent underline. The underline also applies on the
   front page, where the active colour is overridden to pink below. */
.cyclein-global-header__nav .menu-item--active-trail > a {
  color: var(--color-brand-yellow);
  text-decoration: underline;
  text-decoration-thickness: 0.12em;
  text-underline-offset: 0.3em;
}

/* ==========================================================================
   Header account control (round-1 checklist r3 + r15).

   The design closes the header with an account pill: `Log in` for anonymous
   visitors, a `My account` disclosure for signed-in ones. Both come from the
   core `account` menu block placed in the header region, so the links are
   permission-aware without any bridging code, and an editor maintains them at
   /manage/menus. The pill is white on the dark header and dark on the lime
   front-page bar, matching the two supplied frames.
   ========================================================================== */

.cyclein-global-header__account {
  position: relative;
}

.cyclein-global-header__account .menu {
  align-items: center;
  display: flex;
  gap: var(--space-8);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Anonymous: the menu's single Log in link is the pill itself. */
.cyclein-global-header__account .menu a,
.cyclein-global-header__account-toggle {
  align-items: center;
  background: var(--color-brand-white);
  border: 2px solid var(--color-brand-white);
  border-radius: var(--radius-pill);
  color: var(--color-brand-black);
  cursor: pointer;
  display: inline-flex;
  font-family: inherit;
  font-size: var(--type-button-size);
  font-weight: var(--font-weight-bold);
  gap: var(--space-8);
  justify-content: center;
  line-height: var(--type-button-line-height);
  min-block-size: var(--a11y-min-target);
  padding: var(--space-8) var(--space-24);
  text-decoration: none;
  white-space: nowrap;
}

.cyclein-global-header__account .menu a:hover,
.cyclein-global-header__account-toggle:hover {
  background: var(--color-brand-white-hover);
  border-color: var(--color-brand-white-hover);
  color: var(--color-brand-black);
}

/* Disclosure caret. Rotating it on expand pairs the open state with a shape
   change, so the state is not carried by position alone. */
.cyclein-global-header__account-toggle::after {
  background-color: currentColor;
  block-size: 0.5em;
  content: "";
  display: inline-block;
  flex: 0 0 auto;
  inline-size: 0.8em;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l7 7 7-7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l7 7 7-7'/%3E%3C/svg%3E") center / contain no-repeat;
}

.cyclein-global-header__account-toggle[aria-expanded="true"]::after {
  transform: rotate(180deg);
}

/* Signed in: the account links drop out of the trigger as a card. Before the
   behaviour attaches (and with JS off) the panel is a plain in-flow list, so
   the links stay reachable. */
.cyclein-global-header__account-panel[hidden] {
  display: none;
}

.cyclein-global-header__account-panel .menu {
  flex-direction: column;
  gap: var(--space-4);
}

/* Round-3 checklist r11: the open "My account" panel is the dark-teal card from
   the Figma frame — white links, a pink "Log out", not the earlier white panel. */
[data-cyclein-nav-enhanced] .cyclein-global-header__account-panel {
  background: var(--color-brand-black);
  border-radius: var(--radius-24);
  box-shadow: 0 12px 28px rgba(6, 51, 53, 0.35);
  inset-block-start: calc(100% + var(--space-8));
  inset-inline-end: 0;
  min-inline-size: 14rem;
  padding: var(--space-8);
  position: absolute;
  z-index: 5;
}

[data-cyclein-nav-enhanced] .cyclein-global-header__account-panel .menu a {
  background: transparent;
  border-color: transparent;
  border-radius: var(--radius-8);
  color: var(--color-brand-white);
  inline-size: 100%;
  justify-content: flex-start;
  padding-inline: var(--space-16);
}

[data-cyclein-nav-enhanced] .cyclein-global-header__account-panel .menu a:hover {
  background: color-mix(in srgb, var(--color-brand-white) 12%, transparent);
  border-color: transparent;
  color: var(--color-brand-white);
}

/* Log out reads in the brand pink, matching the Figma. */
[data-cyclein-nav-enhanced] .cyclein-global-header__account-panel .menu a[href*="/user/logout"] {
  color: var(--color-brand-pink);
}

[data-cyclein-nav-enhanced] .cyclein-global-header__account-panel .menu a[href*="/user/logout"]:hover {
  color: var(--color-brand-pink);
}

/* Front page: the pill inverts to dark on the lime bar. */
.path-frontpage .cyclein-global-header__account > .menu a,
.path-frontpage .cyclein-global-header__account-toggle {
  background: var(--color-brand-black);
  border-color: var(--color-brand-black);
  color: var(--color-brand-white);
  text-shadow: none;
}

.path-frontpage .cyclein-global-header__account > .menu a:hover,
.path-frontpage .cyclein-global-header__account-toggle:hover {
  background: var(--color-brand-black-hover);
  border-color: var(--color-brand-black-hover);
  color: var(--color-brand-white);
}

@media (min-width: 768px) {
  .cyclein-global-header__toggle {
    display: none;
  }

  .cyclein-global-header__nav {
    display: flex;
  }
}

@media (max-width: 767px) {
  .cyclein-region--header .cyclein-region__inner {
    padding-block: 10px;
    padding-inline: 20px;
  }

  body:not(.path-frontpage) .cyclein-global-header__brand::before,
  .path-frontpage .cyclein-global-header__brand::before {
    block-size: 22px;
    inline-size: 136px;
  }

  .cyclein-global-header[data-cyclein-nav-enhanced] .cyclein-global-header__toggle {
    display: inline-flex;
  }

  /* Icon-only hamburger (Figma mobile header): the "Open menu" / "Close menu"
     label is kept as the accessible name (font-size:0 hides it visually) and a
     three-bar glyph is drawn with a centre bar + two box-shadow bars. */
  .cyclein-global-header__toggle {
    block-size: var(--a11y-min-target);
    border-color: transparent;
    font-size: 0;
    gap: 0;
    inline-size: var(--a11y-min-target);
    padding: 0;
    position: relative;
  }

  .cyclein-global-header__toggle::before {
    background: currentColor;
    block-size: 2px;
    box-shadow: 0 -6px currentColor, 0 6px currentColor;
    content: "";
    inline-size: 22px;
  }

  .cyclein-global-header__nav {
    flex-basis: 100%;
    margin-inline-start: 0;
    order: 6;
  }

  .cyclein-global-header__nav .menu {
    align-items: stretch;
    flex-direction: column;
    row-gap: var(--space-8);
  }

  .cyclein-global-header__nav[hidden] {
    display: none;
  }
}

/* ==========================================================================
   Front page only: the hero disc bleeds to the very top of the page, so the
   header floats transparently over the lime band with dark-teal marks. Every
   rule here is scoped to `.path-frontpage` (added in the theme's
   preprocess_html) so non-front pages keep the solid dark-teal header and white
   wordmark untouched.
   ========================================================================== */

.path-frontpage .cyclein-page {
  --cyclein-front-header-overlap: 111px;
  position: relative;
}

/* Pull the flush main up under the transparent header so the hero — and the
   disc inside it — starts at the top of the page and reads as full-bleed behind
   the header. */
.path-frontpage .cyclein-page__main--flush {
  margin-block-start: calc(-1 * var(--cyclein-front-header-overlap));
  position: relative;
  z-index: 0;
}

.path-frontpage .cyclein-region--header {
  background: transparent;
  position: relative;
  z-index: 3;
}

/* Recolour the wordmark, navigation and toggle on the lime hero. */
.path-frontpage .cyclein-global-header__brand,
.path-frontpage .cyclein-global-header__toggle,
.path-frontpage .cyclein-global-header__nav .menu a {
  color: var(--color-brand-black);
}

.path-frontpage .cyclein-global-header__nav .menu a:hover,
.path-frontpage .cyclein-global-header__nav .menu-item--active-trail > a {
  color: var(--color-brand-pink);
}

/* Give the mobile toggle a lime contrast pill over the hero photograph. */
.path-frontpage .cyclein-global-header__toggle {
  background: var(--color-brand-yellow);
  border-color: transparent;
  border-radius: var(--radius-pill);
  padding-inline: var(--space-16);
}

@media (min-width: 1200px) {
  /* The lime contrast pill wraps the nav links AND the account control. Figma
     sizes the pill larger than the links with the yellow showing above and below
     (checklist R5 row 7); the inter-item spacing matches the base bar (round-8
     r11) at 24px with 40px side padding (round-10 r6).
     Round-3 checklist r2: the Figma closes the header with ONE lime pill holding
     the nav AND the account control. The nav and account are separate blocks, so
     the pill is formed from two abutting halves sharing the lime fill: the nav
     rounds its left edge, the account rounds its right, and the 24px header gap
     between them is cancelled so the fill reads as a single container with the
     dark Log in / My account pill seated inside it.
     Round-4 checklist r2 added a 1px brand-black outline here to define the
     pill's shape on the lime hero; round-5 r2 read that outline as a black border
     absent from the Figma. The design export confirms it: the Nav strokes are
     visible:false — it is a plain lime pill with no outline. Reverted to match
     the design (lime fill only, no border); the pill still reads where the hero
     photo shows through its rounded left edge. */
  .path-frontpage .cyclein-global-header__nav {
    background: var(--color-brand-yellow);
    border-end-start-radius: var(--radius-pill);
    border-start-start-radius: var(--radius-pill);
    gap: var(--space-24);
    padding-block: var(--space-8);
    padding-inline: var(--space-40) var(--space-24);
  }

  .path-frontpage .cyclein-global-header__account {
    background: var(--color-brand-yellow);
    border-end-end-radius: var(--radius-pill);
    border-start-end-radius: var(--radius-pill);
    margin-inline-start: calc(-1 * var(--space-24));
    padding-block: var(--space-8);
    padding-inline: 0 var(--space-8);
  }
}

/* A soft halo keeps dark header marks legible over the hero photograph. */
.path-frontpage .cyclein-global-header__nav .menu a,
.path-frontpage .cyclein-global-header__toggle {
  text-shadow: 0 1px 3px rgba(255, 255, 255, 0.7);
}

.path-frontpage .cyclein-global-header__brand::before {
  filter: drop-shadow(0 1px 2px rgba(255, 255, 255, 0.85));
}

/* Pull the hero behind the single-row mobile header. */
@media (max-width: 767px) {
  .path-frontpage .cyclein-page {
    --cyclein-front-header-overlap: 99px;
  }
}

/* Phone front page: the hero reflows to black-on-lime copy with the disc stacked
   below (see home.css `max-width:640px`), so nothing bleeds behind the header.
   The transparent-overlay header therefore reverts to the solid dark-teal bar
   every other page uses — no pull-up, white marks, no lime contrast pill. */
@media (max-width: 640px) {
  .path-frontpage .cyclein-page {
    --cyclein-front-header-overlap: 0px;
  }

  .path-frontpage .cyclein-region--header {
    background: var(--color-brand-black);
  }

  .path-frontpage .cyclein-global-header__brand,
  .path-frontpage .cyclein-global-header__toggle {
    color: var(--color-brand-white);
    text-shadow: none;
  }

  /* On the solid mobile header the front page adopts the two-tone White & Yellow
     wordmark every other page uses (the transparent-header single-colour mask is
     only for the lime hero). */
  .path-frontpage .cyclein-global-header__brand::before {
    background-color: transparent;
    background-image: url("../images/cyclein-logo-white-yellow.svg");
    background-position: left center;
    background-repeat: no-repeat;
    background-size: contain;
    filter: none;
    -webkit-mask: none;
    mask: none;
  }

  .path-frontpage .cyclein-global-header__toggle {
    background: transparent;
    padding-inline: 0;
  }
}

/* ==========================================================================
   Mobile hamburger menu — collapsed bar + expanded overlay (Figma "Nav Open").

   The theme-owned nav-toggle.js flips aria-expanded and un-hides
   #cyclein-primary-nav. Collapsed, the header is a single brand + hamburger row.
   Expanded, it becomes a full-screen dark-teal panel with the primary links.
   ========================================================================== */
@media (max-width: 767px) {
  /* Tighter bar so brand + cart + hamburger clear a 375px row (the 197px desktop
     wordmark + 24px gaps would otherwise wrap the last control). */
  .cyclein-global-header {
    column-gap: var(--space-16);
  }

  .cyclein-global-header__brand::before {
    block-size: 26px;
    inline-size: 168px;
  }

  /* Single-row collapsed header order: brand left, hamburger right. */
  .cyclein-global-header__brand {
    margin-inline-end: auto;
    order: 0;
  }

  .cyclein-global-header__toggle {
    margin-inline-start: 0;
    order: 2;
  }

  /* Hamburger → X when the menu is open. */
  .cyclein-global-header__toggle[aria-expanded="true"]::before {
    box-shadow: none;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    margin-block-start: -1px;
    margin-inline-start: -11px;
    position: absolute;
    transform: rotate(45deg);
  }

  .cyclein-global-header__toggle[aria-expanded="true"]::after {
    background: currentColor;
    block-size: 2px;
    content: "";
    inline-size: 22px;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    margin-block-start: -1px;
    margin-inline-start: -11px;
    position: absolute;
    transform: rotate(-45deg);
  }

  /* Expanded: the header fills the viewport as the dark-teal menu panel. */
  .cyclein-global-header:has(.cyclein-global-header__toggle[aria-expanded="true"]) {
    align-content: flex-start;
    background: var(--color-brand-black);
    /* The header is `.cyclein-region__inner` (constrained, margin-auto); override
       so `inset:0` can stretch the fixed panel edge-to-edge. */
    inline-size: auto;
    inset: 0;
    margin-inline: 0;
    max-inline-size: none;
    overflow-y: auto;
    padding: var(--space-8) 20px var(--space-48);
    position: fixed;
    row-gap: 0;
    z-index: 60;
  }

  /* Keep the open panel below Drupal's mobile toolbar for authenticated users;
     core owns this displacement value and updates it as its toolbar changes. */
  body:has(#toolbar-administration) .cyclein-global-header:has(.cyclein-global-header__toggle[aria-expanded="true"]) {
    inset-block-start: var(--drupal-displace-offset-top, 51px);
  }

  /* Round-12 MM3: on the front page content_top (z-index:4) sits above the
     header region (z-index:3), so the open mobile menu — z-index:60 but confined
     to the header's stacking context — rendered below the editor local-task
     tabs, which bled over the menu. Lift the header region above content_top
     while the menu is open so the full-screen panel covers the tabs. */
  .cyclein-region--header:has(.cyclein-global-header__toggle[aria-expanded="true"]) {
    position: relative;
    z-index: 20;
  }

  /* Every mark in the open panel is white on the teal (front page included). */
  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__brand,
  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__toggle {
    color: var(--color-brand-white);
    text-shadow: none;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__toggle {
    background: transparent;
    padding-inline: 0;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__brand::before {
    filter: none;
  }

  /* Primary nav: full-width chevroned rows under the top row. */
  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__nav {
    background: var(--color-brand-black);
    flex-basis: calc(100% + 8px);
    inline-size: calc(100% + 8px);
    /* 38px places the first row at y=113 in the 375px content viewport, which
       is the supplied guest-menu frame after its 52px device chrome. */
    margin-block-start: 38px;
    margin-inline: -4px;
    order: 3;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__nav .menu {
    border-block-end: 1px solid color-mix(in srgb, var(--color-brand-white) 35%, transparent);
    padding-block-end: 14px;
    row-gap: 0;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__nav .menu a {
    align-items: center;
    color: var(--color-brand-white);
    display: flex;
    font-size: var(--type-body-large-size);
    font-weight: var(--font-weight-bold);
    justify-content: space-between;
    min-block-size: var(--space-64);
    padding-block: 0;
    padding-inline: var(--space-12) 22px;
    text-shadow: none;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__brand::before {
    inline-size: 136px;
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__nav .menu a::after {
    content: "\203A";
    font-weight: var(--font-weight-bold);
    margin-inline-start: var(--space-16);
  }

  .cyclein-global-header:has([aria-expanded="true"]) .cyclein-global-header__nav .menu a:hover {
    color: var(--color-brand-yellow);
  }

}

/* ==========================================================================
   Status messages.

   No system messages block is placed, so core renders messages at the top of
   the content region. Brand them as legible alert banners centred in the
   content column. On the front page the flush main is pulled up under the
   transparent header, so a message is pushed clear of the header (and reads as
   a confirmation banner above the hero) rather than overlapping the wordmark.
   ========================================================================== */

[data-drupal-messages] {
  inline-size: var(--cyclein-container);
  margin-block: var(--space-24);
  margin-inline: auto;
}

[data-drupal-messages] [role="contentinfo"],
[data-drupal-messages] [role="alert"] {
  border-radius: var(--radius-8);
  color: var(--color-brand-black);
  font-size: var(--type-body-size);
  font-weight: var(--font-weight-bold);
  padding: var(--space-16) var(--space-24);
}

/* Colour by message type (the aria-label carries the status heading). */
[data-drupal-messages] [aria-label="Status message"] {
  background: var(--color-brand-lime-tint);
  border-inline-start: 6px solid var(--color-success);
}

[data-drupal-messages] [aria-label="Warning message"] {
  background: var(--color-brand-yellow-tint);
  border-inline-start: 6px solid var(--color-warning);
}

[data-drupal-messages] [aria-label="Error message"] {
  background: var(--color-brand-pink-tint);
  border-inline-start: 6px solid var(--color-error);
}

[data-drupal-messages] a {
  color: var(--color-brand-black);
}

/* Front page: reserve room for the banner the pulled-up main would otherwise
   cover.

   Round-1 checklist r11: the clearance was on the WRONG side. The messages
   block sits in `highlighted`, above `main`, so it never needed clearing from
   the header — but `main--flush` is pulled up 111px, which is more than the
   83px a banner contributes to the flow, so the hero slid up over the
   confirmation and it read as debris floating on the lime band (measured: hero
   top 606.5px against a message box at 634.5px). Moving the clearance to the
   end, and sizing it as the overlap plus the normal gap, cancels the pull-up
   for the banner only: the hero now starts one 24px gap below it, and the
   highlighted band no longer opens with 135px of dead space above the text. */
.path-frontpage [data-drupal-messages] {
  margin-block-end: calc(var(--cyclein-front-header-overlap, 111px) + var(--space-24));
  margin-block-start: var(--space-24);
  position: relative;
  z-index: 4;
}

/* ==========================================================================
   Breadcrumb trail (content_top region).
   ========================================================================== */

/* The breadcrumb block is dropped from content_top site-wide (see
   cyclein_public_preprocess_page), so the region is empty on most pages. Only
   pad it when it actually carries content; otherwise it collapses. */
.cyclein-region--content-top .cyclein-region__inner:has(*) {
  padding-block: var(--space-16);
}

/* Render the trail as a plain inline list: suppress the ordered-list marker so
   it never reads as "1. Home". */
.cyclein-region--content-top nav[aria-labelledby="system-breadcrumb"] ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  list-style: none;
  margin: 0;
  padding: 0;
}

.cyclein-region--content-top nav[aria-labelledby="system-breadcrumb"] li {
  align-items: center;
  color: var(--color-brand-black-muted);
  display: inline-flex;
  font-size: var(--type-mobile-label-size);
  gap: var(--space-8);
}

.cyclein-region--content-top nav[aria-labelledby="system-breadcrumb"] li:not(:first-child)::before {
  color: var(--color-brand-black-muted);
  content: "/";
}

.cyclein-region--content-top nav[aria-labelledby="system-breadcrumb"] a {
  color: var(--color-brand-black-muted);
  font-weight: var(--font-weight-regular);
  text-decoration: none;
}

.cyclein-region--content-top nav[aria-labelledby="system-breadcrumb"] a:hover {
  color: var(--color-brand-black);
  text-decoration: underline;
}

/* ==========================================================================
   Need help? support card (pre-footer region).
   ========================================================================== */

/* Round-8 r37/r39: the prototype outlines this card in the brand green
   (#00ff00), not pink. */
/**
 * Round-10 checklist r23: the reported defect was the card's LAYOUT (the stale
 * staging build stacked "Contact us" above "Need help?" with the body pushed
 * right); the current build already renders the design's order — heading, body,
 * then the action on the right — so no layout change was needed.
 *
 * The border is --color-brand-lime (#00ff00), per the round-12 client override
 * (checklist r15/r16), applied to every "Need help?" CTA.
 *
 * History: round-10 settled this on pink #d41166 from the Figma node
 * (333:30032), because the QC crop then showed lime but the design node was
 * pink. Round-12's QC reverses that — the client now wants green #00FF00 on all
 * these CTAs — so this is a client-directed deviation from the Figma node,
 * superseding the 2026-07-16 pink decision.
 */
.cyclein-region--pre-footer #block-cyclein-public-need-help {
  align-items: center;
  background: var(--color-white);
  border: 2px solid var(--color-brand-lime);
  border-radius: var(--radius-24);
  column-gap: var(--space-40);
  display: grid;
  grid-template-columns: 1fr auto;
  /* The design's card is padded 32 on all four sides, not 32/40 — its own box
     is 1200x152 and its content 952x88, which 32 top and bottom accounts for
     exactly (node 333:30032). */
  padding: var(--space-32);
}

/* The heading took the h3 size but not its line-height, so it inherited the
   body's 1.5 and rendered 25px/37.5px where the design has 25px/32.5px — the
   h3 token's own 1.3. */
.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(1) {
  color: var(--color-brand-black);
  font-size: var(--type-h3-size);
  font-weight: var(--font-weight-black);
  grid-column: 1;
  grid-row: 1;
  line-height: var(--type-h3-line-height);
}

.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(2) {
  color: var(--color-brand-black-muted);
  grid-column: 1;
  grid-row: 2;
}

.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(2) p {
  margin: 0;
}

.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) {
  grid-column: 2;
  grid-row: 1 / 3;
  justify-self: end;
}

/* Round-8 r37/r39: the CTA is the light-grey pill with dark-teal text, not a
   filled dark-teal button.

   Round-10 r23: it is a button, so it belongs on the button token — the design
   sets "Contact us" at 20px/24px w700, which is exactly --type-button (20px) x
   --type-button-line-height (1.2). It was rendering at the inherited 18px/27px. */
.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) a {
  align-items: center;
  background: var(--color-brand-white);
  border-radius: var(--radius-pill);
  color: var(--color-brand-black);
  display: inline-flex;
  font-size: var(--type-button-size);
  font-weight: var(--font-weight-bold);
  gap: var(--space-8);
  line-height: var(--type-button-line-height);
  min-block-size: var(--a11y-min-target);
  padding: var(--space-12) var(--space-24);
  text-decoration: none;
  white-space: nowrap;
}

.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) a::after {
  content: "\2192";
  font-weight: var(--font-weight-bold);
}

/* Round-2 checklist r6: the "Need help?" Contact us CTA had no hover state. Give
   it the same brand-yellow hover the header account pill uses, so it reads as an
   interactive control consistent with every other button. */
.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) a {
  transition: background-color 140ms ease, color 140ms ease;
}

.cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) a:hover {
  background: var(--color-brand-yellow);
  color: var(--color-brand-black);
}

@media (max-width: 640px) {
  .cyclein-region--pre-footer #block-cyclein-public-need-help {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-24);
  }

  .cyclein-region--pre-footer #block-cyclein-public-need-help > div:nth-child(3) {
    grid-column: 1;
    grid-row: 3;
    justify-self: start;
  }
}

/* ==========================================================================
   Global footer.
   ========================================================================== */

/* A full-width lime rule separates the footer band from the content above it,
   matching the prototype divider between the pre-footer CTA and the footer. */
.cyclein-region--footer {
  border-block-start: 2px solid var(--color-brand-yellow);
}

.cyclein-region--footer .cyclein-region__inner {
  padding-block: var(--space-80);
}

/* Round-11 checklist r3: the between-column gap is the design's 24px, not 48px
   (the footer "Frame" itemSpacing is 24). The row also reports the 1920 left/
   right gutters, but those are the contract-mandated 1200px content cap that the
   header and every page section share (global_footer.md L51, P001 L172) — the
   footer background is full-bleed, its content capped, by design — so only the
   in-cap column gap is corrected here. */
.cyclein-global-footer {
  display: grid;
  gap: var(--space-40) var(--space-24);
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

/* Round-12 CM2: at phone widths the auto-fit base track (minmax(180px,1fr))
   still seated two columns, so the five footer sections laid out 2-up and read
   out of order. Force a single stacked column below the mobile breakpoint; the
   block weights (brand → Explore → Support → Bikeability → base) then render
   the design's line-by-line order. The tablet range (768–999px) keeps auto-fit,
   desktop keeps the four-column band. */
@media (max-width: 767px) {
  .cyclein-global-footer {
    grid-template-columns: 1fr;
  }
}

/* Desktop: four evenly balanced columns (wordmark, Explore, Support, Bikeability
   Trust), mirroring the prototype's four-up footer band. */
@media (min-width: 1000px) {
  .cyclein-region--footer .cyclein-region__inner {
    padding-block: 144px;
  }

  .cyclein-global-footer {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* Each footer section is its own block placed in the footer region (R5 row 3);
   Drupal hoists the section's BEM class onto the block wrapper, so the wrappers
   are the grid columns directly — no display:contents flattening is needed. */

/* Footer wordmark: the two-colour White & Yellow brand logo on the dark-teal
   footer band, matching the header brand treatment (round-8 r7 — the footer
   shipped the single-colour mask, which painted the whole wordmark white and
   lost the lime "IN"). */
.cyclein-global-footer__brand {
  align-items: center;
  align-self: start;
  color: var(--color-brand-white);
  display: inline-flex;
  font-size: 0;
  min-block-size: var(--a11y-min-target);
  position: relative;
  text-decoration: none;
}

/* The brand is now a block wrapper carrying the mask logo (::before); the inner
   link overlays it so the whole wordmark stays clickable with its text hidden
   (R5 row 3 — footer split). */
.cyclein-global-footer__brand a {
  font-size: 0;
  inset: 0;
  position: absolute;
  text-decoration: none;
}

/* Painted as a background image, not a currentColor mask: the asset is a genuine
   two-tone SVG (lime "IN" + white "CYCLE"). Aspect 1428.71:235.57 → 28px tall
   sets the inline size at 170px. */
.cyclein-global-footer__brand::before {
  background-color: transparent;
  background-image: url("../images/cyclein-logo-white-yellow.svg");
  background-position: left center;
  background-repeat: no-repeat;
  background-size: contain;
  block-size: 28px;
  content: "";
  display: block;
  inline-size: 170px;
  max-inline-size: 100%;
  -webkit-mask: none;
  mask: none;
}

.cyclein-global-footer h2 {
  color: var(--color-brand-yellow);
  font-size: var(--type-body-large-size);
  margin-block-end: var(--space-16);
}

.cyclein-global-footer__bikeability h2 a {
  color: inherit;
  text-decoration: none;
}

.cyclein-global-footer__bikeability h2 a:hover {
  text-decoration: underline;
}

.cyclein-global-footer__menu .menu {
  display: grid;
  gap: var(--space-16);
  list-style: none;
  margin: 0;
  padding: 0;
}

.cyclein-global-footer__menu .menu a {
  color: var(--color-brand-white);
  font-weight: var(--font-weight-regular);
  text-decoration: none;
}

.cyclein-global-footer__menu .menu a:hover {
  text-decoration: underline;
}

.cyclein-global-footer__bikeability p {
  color: var(--color-brand-black-tint);
  margin: 0;
}

/* Social channels: white glyphs sit as dark marks inside white circles, per the
   prototype. Each link is an accessible target with an aria-label; the platform
   name is retained as a font-size:0 fallback and the glyph is painted via mask. */
.cyclein-global-footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-12);
  list-style: none;
  margin: var(--space-16) 0 0;
  padding: 0;
}

.cyclein-global-footer__social-link {
  align-items: center;
  background-color: var(--color-brand-white);
  block-size: var(--a11y-min-target);
  border-radius: var(--radius-pill);
  color: var(--color-brand-black);
  display: inline-flex;
  font-size: 0;
  inline-size: var(--a11y-min-target);
  justify-content: center;
  text-decoration: none;
}

.cyclein-global-footer__social-link:hover {
  background-color: var(--color-brand-yellow);
}

.cyclein-global-footer__social-link::before {
  background-color: currentColor;
  block-size: 22px;
  content: "";
  display: block;
  inline-size: 22px;
}

.cyclein-global-footer__social-link--x::before {
  -webkit-mask: url("../images/social-x.svg") center / contain no-repeat;
  mask: url("../images/social-x.svg") center / contain no-repeat;
}

.cyclein-global-footer__social-link--instagram::before {
  -webkit-mask: url("../images/social-instagram.svg") center / contain no-repeat;
  mask: url("../images/social-instagram.svg") center / contain no-repeat;
}

.cyclein-global-footer__social-link--facebook::before {
  -webkit-mask: url("../images/social-facebook.svg") center / contain no-repeat;
  mask: url("../images/social-facebook.svg") center / contain no-repeat;
}

.cyclein-global-footer__social-link--linkedin::before {
  -webkit-mask: url("../images/social-linkedin.svg") center / contain no-repeat;
  mask: url("../images/social-linkedin.svg") center / contain no-repeat;
}

/* Partner row + copyright share a single base band across all footer columns.
   A pseudo-element paints the divider rule at full viewport width (the reviewer
   asked for a full-bleed grey line), while the content stays in the column. */
.cyclein-global-footer__base {
  align-items: flex-start;
  column-gap: var(--space-48);
  display: flex;
  flex-wrap: wrap;
  grid-column: 1 / -1;
  justify-content: space-between;
  padding-block-start: var(--space-56);
  position: relative;
  row-gap: var(--space-24);
}

/* The copyright sits level with the partner logos rather than the labels. */
.cyclein-global-footer__base .cyclein-global-footer__copyright {
  align-self: center;
}

.cyclein-global-footer__base::before {
  border-block-start: 1px solid var(--color-green-dark);
  content: "";
  inline-size: 100vw;
  inset-block-start: 0;
  inset-inline-start: calc(50% - 50vw);
  position: absolute;
}

.cyclein-global-footer__partners {
  align-items: flex-start;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-48);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Round-1 checklist r6: the partner captions sat on their own 48px flex rhythm
   (measured x = 120 / 364 / 586) while the four footer columns above them sit on
   the band's 4-track grid (x = 120 / 426 / 732 / 1038), so only the first column
   lined up and the base row read as a separate, narrower block. The design
   aligns both rows on one grid. Re-laying the base row on the same four tracks
   — partners occupying the first three, copyright the fourth — makes the
   captions inherit the columns above them exactly. */
@media (min-width: 1000px) {
  .cyclein-global-footer__base {
    column-gap: var(--space-24);
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .cyclein-global-footer__partners {
    display: grid;
    gap: var(--space-24);
    grid-column: 1 / 4;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .cyclein-global-footer__base .cyclein-global-footer__copyright {
    grid-column: 4;
    justify-self: end;
  }
}

/* Each partner label tops its column and every label lines up on one baseline,
   regardless of the differing logo heights below it. */
.cyclein-global-footer__partner {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  /* Figma leaves more breathing room between each partner caption and its logo
     than the 24px the column shipped with (round-6 issue r12). Round-8 r13
     measured the design's caption→logo gap ~20% wider again. */
  gap: var(--space-40);
}

/* Real partner logos (Bikeability, Williams Lea | TSO, forest) sit directly on
   the dark teal band as in Figma — no card. The Bikeability mark and the forest
   badge carry their own light/colour artwork; the single-colour Williams Lea |
   TSO mark is dark, so it is painted white via a filter to stay legible. The
   placeholder "Logo" text is hidden via font-size:0 while the span keeps its
   role="img" + aria-label. */
.cyclein-global-footer__partner-logo {
  background-position: left center;
  background-repeat: no-repeat;
  background-size: contain;
  display: inline-block;
  font-size: 0;
}

.cyclein-global-footer__partners > li:nth-child(1) .cyclein-global-footer__partner-logo {
  background-image: url("../images/bikeability.svg");
  block-size: 52px;
  inline-size: 196px;
}

.cyclein-global-footer__partners > li:nth-child(2) .cyclein-global-footer__partner-logo {
  background-image: url("../images/tso.png");
  block-size: 24px;
  filter: brightness(0) invert(1);
  inline-size: 174px;
}

.cyclein-global-footer__partners > li:nth-child(3) .cyclein-global-footer__partner-logo {
  background-image: url("../images/forest.png");
  block-size: 52px;
  inline-size: 102px;
}

/* Round-8 r13: the captions are lime, not white, and sit well below the body
   scale — they are eyebrow labels over each logo, not body copy. Measured
   scale-free against the partner marks in the same frame, the design caption is
   ~0.7× the 16px the column shipped with; the type scale bottoms out at 16px,
   so the eyebrow size is set here rather than inventing a global token. */
.cyclein-global-footer__partner-caption {
  color: var(--color-brand-yellow);
  font-size: 12px;
  font-weight: var(--font-weight-bold);
}

.cyclein-global-footer__copyright {
  color: var(--color-brand-black-tint);
  margin: 0;
}

/* ==========================================================================
   Admin toolbar — core's own sizing stands (front-end included).

   Round-10 checklist r3 reports the toolbar on the public theme as too small
   and asks for it "theo chuẩn drupal" — Drupal standard. This block used to do
   the opposite: it was "C7 — Admin toolbar compacting", which shrank the tray
   (8px block padding, 16px icons) so it read as less dominant over the brand
   pages, on client feedback from an earlier round.

   Those two instructions contradict each other, and this round's wins: it is
   the later word from the same client, via their own QC. So the compacting is
   removed and core's sizing is left alone. That also settles it in the
   direction the round-8 r6 note already argued on principle — "the toolbar is
   admin UI, not brand surface" — which is the reason the labels were handed
   back to core's 13px then, rather than pinned to a brand token.

   Kept deliberately: the reset-neutralising rules near the top of this file
   (round-6 r11). Those fix the theme's own resets leaking into the toolbar and
   knocking its links and icons out of alignment. They restore core's
   appearance rather than override it, so they are not part of the compacting.

   If the earlier "less dominant" preference is reinstated, this is the block to
   put back — but it should be settled between C7 and r3 first, not toggled.
   ========================================================================== */

/**
 * Round-9 checklist mobile r7: the partner list is a wrapping flex row, so on a
 * phone "Learning provider" and "Launch sponsor" fell onto the same line. The
 * design gives each partner its own line, so stack them below the footer's
 * multi-column breakpoint.
 */
@media (max-width: 767px) {
  .cyclein-region--footer .cyclein-region__inner {
    padding-block: var(--space-48);
  }

  .cyclein-global-footer__partners {
    flex-direction: column;
    gap: var(--space-32);
  }

  .cyclein-global-footer__partner {
    inline-size: 100%;
  }

  .cyclein-global-footer {
    row-gap: var(--space-32);
  }
}
