/*
 * The floating invitation that replaced the header's subscribe button.
 *
 * It borrows the header's own material — the soft sheen over the page surface, the hairline ring,
 * the glass shadow and the velvet glow, the corners that are square above and round below — so it
 * reads as another part of the same bar rather than as an advertisement someone bolted on.
 *
 * Every colour here is an existing site token. Nothing in this file defines one.
 *
 * Geometry, in one place so it cannot drift:
 *   - the wrapper is fixed below `--site-header-h` and never reaches up into the header;
 *   - it is `pointer-events: none`, so the page behind it stays clickable everywhere but the card;
 *   - it sits at `z-index: 40`, under the header (50) and the skip link (60), so the mobile sheet
 *     that drops out of the header covers it rather than fighting it;
 *   - the 16px gutter is the wrapper's own padding, so the card can be `100%` wide and still keep
 *     its margins on the narrowest phone;
 *   - the card wraps its row instead of overflowing, and the close button is out of that flow.
 */

[data-component="agent-nudge"] {
  position: fixed;
  inset-inline: 0;
  top: calc(var(--site-header-h) + 10px);
  z-index: 40;
  display: flex;
  justify-content: center;
  padding-inline: 16px;
  pointer-events: none;
}

/* The header's sheet comes down over exactly this space; two cards there would be one too many. */
:root[data-site-menu="open"] [data-component="agent-nudge"] {
  display: none;
}

[data-component="agent-nudge"] [data-slot="card"] {
  position: relative;
  box-sizing: border-box;
  width: min(32rem, 100%);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 0.9rem;
  /* Logical, so the room kept for the close button is on the closing side in Arabic too. */
  padding-block: 0.7rem;
  padding-inline: 0.8rem 2.25rem;
  border-radius: 10px 10px 20px 20px;
  background: var(--site-sheen-soft), var(--site-surface);
  box-shadow: inset 0 0 0 1px var(--site-hairline), var(--site-glass-shadow), var(--site-velvet-glow);
  color: var(--site-text);
  font-size: 0.875rem;
  line-height: 1.35;
  pointer-events: auto;
  animation: nudge-rise 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}

[data-component="agent-nudge"] a:focus-visible,
[data-component="agent-nudge"] button:focus-visible {
  outline: 2px solid var(--site-focus);
  outline-offset: 2px;
}

[data-component="agent-nudge"] [data-slot="line"] {
  flex: 1 1 10rem;
  min-width: 0;
  margin: 0;
  color: var(--site-text-strong);
  text-wrap: pretty;
}

/* Compact on purpose: an invitation, not a banner. */
[data-component="agent-nudge"] [data-slot="buy"] {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.8rem;
  border-radius: 7px 7px 11px 11px;
  background: var(--site-accent);
  color: var(--site-accent-fg);
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.18s ease;
}

[data-component="agent-nudge"] [data-slot="buy"]:hover {
  background: var(--site-accent-hover);
}

/* Out of the flex flow, so the row can wrap without the close button chasing it down a line. */
[data-component="agent-nudge"] [data-slot="close"] {
  position: absolute;
  top: 6px;
  inset-inline-end: 6px;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--site-text-weak);
  cursor: pointer;
  transition:
    background-color 0.18s ease,
    color 0.18s ease;
}

[data-component="agent-nudge"] [data-slot="close"]:hover,
[data-component="agent-nudge"] [data-slot="close"]:focus-visible {
  background: var(--site-hover-bg);
  color: var(--site-hover-fg);
}

/* --- the agents at work ----------------------------------------------------------------------
 *
 * Three agents on a ring, each holding a thread to the same centre, the threads running inward.
 * The resting state — every animation removed — is the finished picture, which is what a reader
 * who asked for no motion gets.
 */

[data-component="agent-nudge"] [data-slot="scene"] {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  overflow: visible;
}

[data-component="agent-nudge"] [data-slot="ring"] {
  fill: none;
  stroke: var(--site-hairline);
  stroke-width: 1.25;
  stroke-dasharray: 2 7;
  transform-box: view-box;
  transform-origin: 32px 32px;
  animation: nudge-turn 12s linear infinite;
}

[data-component="agent-nudge"] [data-slot="threads"] path {
  fill: none;
  stroke: var(--site-hover-border);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 3 6;
  stroke-opacity: 0.55;
  animation: nudge-flow 1.8s linear infinite;
}

[data-component="agent-nudge"] [data-slot="threads"] path:nth-child(2) {
  animation-delay: -0.6s;
}

[data-component="agent-nudge"] [data-slot="threads"] path:nth-child(3) {
  animation-delay: -1.2s;
}

[data-component="agent-nudge"] [data-slot="agents"] circle {
  fill: var(--site-hover-border);
  transform-box: fill-box;
  transform-origin: center;
  animation: nudge-breathe 2.6s ease-in-out infinite;
}

[data-component="agent-nudge"] [data-slot="agents"] circle:nth-child(2) {
  animation-delay: -0.85s;
}

[data-component="agent-nudge"] [data-slot="agents"] circle:nth-child(3) {
  animation-delay: -1.7s;
}

[data-component="agent-nudge"] [data-slot="goal"] {
  fill: var(--site-accent);
  transform-box: fill-box;
  transform-origin: center;
  animation: nudge-pulse 2.6s ease-in-out infinite;
}

@keyframes nudge-rise {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
}

@keyframes nudge-turn {
  to {
    transform: rotate(360deg);
  }
}

/* The dash pattern walks back along a path drawn from the centre outward: the work moves inward. */
@keyframes nudge-flow {
  to {
    stroke-dashoffset: 9;
  }
}

@keyframes nudge-breathe {
  50% {
    opacity: 0.5;
    transform: scale(1.14);
  }
}

@keyframes nudge-pulse {
  50% {
    transform: scale(1.09);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-component="agent-nudge"],
  [data-component="agent-nudge"] * {
    animation: none !important;
    transition: none !important;
  }
}
[data-component="dropdown"] {
  position: relative;

  [data-slot="trigger"] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: none;
    border-radius: var(--border-radius-sm);
    background-color: transparent;
    color: var(--color-text);
    font-size: var(--font-size-sm);
    font-family: var(--font-sans);
    cursor: pointer;
    transition: all 0.15s ease;

    &:hover {
      background-color: var(--color-surface-hover);
    }

    span {
      flex: 1;
      text-align: start;
      font-weight: 500;
    }
  }

  [data-slot="chevron"] {
    flex-shrink: 0;
    color: var(--color-text-secondary);
  }

  [data-slot="dropdown"] {
    position: absolute;
    top: 100%;
    z-index: var(--z-menu);
    margin-top: var(--space-1);
    border: 1px solid var(--color-border);
    border-radius: var(--border-radius-sm);
    background-color: var(--color-bg);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    min-width: 160px;

    &[data-align="left"] {
      left: 0;
    }

    &[data-align="right"] {
      right: 0;
    }

    :root[data-theme="dark"] & {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    }
  }

  /*
   * One row definition for all three of the menus built on this component: the plain item, the role
   * picker's richer row (routes/workspace/[id]/members/role-dropdown.css) and the workspace
   * picker's "create" row (routes/workspace-picker.css). All three carried their own copy of these
   * declarations, identical but for the slot name, which is why they never looked like duplicates.
   */
  [data-slot="item"],
  [data-slot="role-item"],
  [data-slot="create-item"] {
    display: block;
    width: 100%;
    padding: var(--space-2-5) var(--space-3);
    border: none;
    border-radius: var(--border-radius-sm);
    background: none;
    color: var(--color-text);
    font-size: var(--font-size-sm);
    font-family: var(--font-sans);
    text-align: start;
    cursor: pointer;
    transition: background-color 0.15s ease;

    &:hover {
      background-color: var(--color-bg-surface);
    }

    &[data-selected="true"] {
      background-color: var(--color-accent-alpha);
    }
  }

  [data-slot="dropdown"] :is(a, button):focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
  }
}
[data-component="language-picker"] {
  width: auto;
}

[data-component="footer"] [data-component="language-picker"] {
  width: 100%;
}

[data-component="footer"] [data-component="language-picker"] [data-component="dropdown"] {
  width: 100%;
}

/* Standard site footer (grid of cells) */
[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] {
  height: 100%;
}

[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"] {
  width: 100%;
  padding: 2rem 0;
  border-radius: 0;
  justify-content: center;
  gap: var(--space-2);
  color: inherit;
  font: inherit;
}

[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"] span {
  flex: 0 0 auto;
  text-align: center;
  font-weight: inherit;
}

[data-component="footer"] [data-slot="cell"] [data-component="language-picker"] [data-slot="trigger"]:hover {
  background: var(--color-background-weak);
  text-decoration: underline;
  text-underline-offset: var(--space-1);
  text-decoration-thickness: 1px;
}

/* Footer dropdown should open upward */
[data-component="footer"] [data-component="language-picker"] [data-slot="dropdown"] {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: var(--space-2);
  max-height: min(60vh, 420px);
  overflow: auto;
}

[data-component="legal"] {
  flex-wrap: wrap;
  row-gap: var(--space-2);
}

[data-component="legal"] [data-component="language-picker"] {
  width: auto;
}

[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"] {
  padding: 0;
  border-radius: 0;
  background: transparent;
  font: inherit;
  color: var(--color-text-weak);
  white-space: nowrap;
}

[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"] span {
  font-weight: inherit;
}

[data-component="legal"] [data-component="language-picker"] [data-slot="trigger"]:hover {
  background: transparent;
  color: var(--color-text);
  text-decoration: underline;
  text-underline-offset: var(--space-1);
  text-decoration-thickness: 1px;
}

[data-component="legal"] [data-component="language-picker"] [data-slot="dropdown"] {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: var(--space-2);
  max-height: min(60vh, 420px);
  overflow: auto;
}
/**
 * The plan reminder.
 *
 * In the flow, not floating. `agent-nudge.css` draws a card that hovers over the page and leaves by
 * itself, because it is talking to somebody who has not bought anything and must be easy to ignore.
 * This is the opposite case: the reader already pays, the message concerns money they are about to
 * spend or stop spending, and covering the page with it — or taking it away on a timer while they
 * read — would both be wrong. So it takes its own row above the content and stays until dismissed.
 *
 * It declares no colour of its own. It sets `--surface` to the raised surface and then writes only
 * `var(--ink…)`, so its text is resolved against the panel it is actually painted on and inverts
 * with the theme without a second palette existing anywhere.
 */

[data-component="plan-reminder"] {
  /* The surface this sits on, which is what every ink token below is resolved against. */
  --surface: var(--surface-raised);

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  inline-size: min(64rem, 100% - 2rem);
  margin: 1rem auto 0;
  padding: 0.85rem 1.1rem;
  border: 1px solid var(--line-strong);
  border-radius: 0.7rem;
  background: var(--surface);
  color: var(--ink-body);
}

[data-component="plan-reminder"] [data-slot="body"] {
  /* Takes the room that is left, and may shrink — without this a long plan name refuses to wrap. */
  flex: 1 1 18rem;
  min-inline-size: 0;
}

[data-component="plan-reminder"] [data-slot="title"] {
  margin: 0;
  color: var(--ink);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.35;
}

[data-component="plan-reminder"] [data-slot="detail"] {
  margin: 0.25rem 0 0;
  /* Body ink, not muted: this is the sentence that explains the money. */
  color: var(--ink-body);
  font-size: 0.875rem;
  line-height: 1.5;
}

[data-component="plan-reminder"] [data-slot="actions"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  /* Pushed to the end on a wide row; falls under the text once the row wraps. */
  margin-inline-start: auto;
}

[data-component="plan-reminder"] :is([data-slot="go"], [data-slot="later"]) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 2.25rem;
  padding-inline: 0.95rem;
  border-radius: 0.5rem;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 120ms ease,
    border-color 120ms ease,
    color 120ms ease;
}

[data-component="plan-reminder"] [data-slot="go"] {
  border: 1px solid var(--site-accent);
  background: var(--site-accent);
  color: var(--site-accent-fg);
}

[data-component="plan-reminder"] [data-slot="go"]:hover {
  background: var(--site-accent-hover, var(--site-accent));
  border-color: var(--site-accent-hover, var(--site-accent));
}

[data-component="plan-reminder"] [data-slot="later"] {
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink-body);
}

[data-component="plan-reminder"] [data-slot="later"]:hover {
  border-color: var(--ink);
  color: var(--ink);
}

[data-component="plan-reminder"] :is(a, button):focus-visible {
  outline: 2px solid var(--site-focus);
  outline-offset: 2px;
}

@media (max-width: 40rem) {
  [data-component="plan-reminder"] {
    /* The 16px side gutter the rest of the site keeps on a phone. */
    inline-size: calc(100% - 2rem);
  }

  [data-component="plan-reminder"] [data-slot="actions"] {
    inline-size: 100%;
    margin-inline-start: 0;
  }

  [data-component="plan-reminder"] :is([data-slot="go"], [data-slot="later"]) {
    /* Two real targets rather than two words squeezed against the edge. */
    flex: 1 1 auto;
  }
}
/*
 * The site bar and the site footer of www.aicippy.com, drawn once.
 *
 * Two renderers put this chrome on the page — the Astro/Starlight documentation in `packages/web`
 * and the SolidStart console in `packages/console/app` — and until this file existed each of them
 * carried its own copy of the glass tray, the centre-out underline, the brand lockup, the drawer
 * and the breakpoints, kept in step by a comment in each file asking the next reader to remember.
 * They drifted: the console's rail links had adopted the lift of the interaction contract and the
 * documentation's had not, and the two bars no longer inverted the same way on hover. What a
 * reader saw was the menu changing between one page and the next.
 *
 * ## What each side still owns
 *
 * The *shell* — the element that is fixed to the top of the viewport, carries the glass and the
 * velvet edge, and reserves its own height — is deliberately not here. It is not the same element
 * on the two sides and it cannot be: on the console it is our own `<header>`, sized by
 * `--site-header-h`; on the documentation it is Starlight's `header.header`, sized by
 * `--sl-nav-height`, padded by `custom.css`, and padded again by Starlight when a sidebar is
 * present. Everything *inside* the shell is here.
 *
 * ## Wiring
 *
 * Put `data-site-bar` on the shell and give it a `[data-slot="bar"]` child for the row. Every
 * other piece is named by `data-slot`. The colours come from `--bar-*` custom properties, which
 * each site maps onto its own palette in one short block — the documentation in
 * `packages/web/src/styles/brand.css`, the console in
 * `packages/console/app/src/component/site-layout.css` — so this file states the appearance and
 * neither site states it twice.
 *
 * Load `interactive.css` beside this file: the links, the sign-in and the drawer rows carry
 * `data-lift` and take their hover from that contract.
 */

/* --- the row -------------------------------------------------------------------------------- */

[data-site-bar] [data-slot="bar"] {
  box-sizing: border-box;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: 0.875rem;
  line-height: 1;
  color: var(--bar-ink);
}

/* The focus ring says *where you are*, which is a different question from the hover's *this does
   something* — so it is here for everything in the bar, including the controls each renderer
   brings with it, rather than only for the ones carrying the interaction contract. */
[data-site-bar] :is(a, button, summary):focus-visible {
  outline: 2px solid var(--bar-focus);
  outline-offset: 2px;
}

/* --- brand ---------------------------------------------------------------------------------- */

[data-site-bar] [data-slot="brand"] {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  height: 40px;
  padding: 4px 6px;
  margin-inline-start: -6px;
  border-radius: 10px;
  color: var(--bar-brand);
  text-decoration: none;
}

[data-site-bar] [data-component="brand-mark"] {
  display: block;
  height: 30px;
  width: auto;
  aspect-ratio: 4 / 1;
}

/*
 * The wordmark is a logotype, not a sentence.
 *
 * SVG `<text>` inherits `direction` from the page, so on the Arabic pages the brand was laid out
 * right-to-left: the glyph run was reordered and `textLength` stopped being honoured, so "AicippY"
 * rendered reversed and squashed to 76px of the 404 it declares. Isolating it pins the one string
 * on the site that must never be reordered, in any locale.
 */
[data-site-bar] [data-component="brand-mark"] text {
  direction: ltr;
  unicode-bidi: isolate;
}

/* --- the navigation tray -------------------------------------------------------------------- */

/* Square where it meets the bar, round below: the tray reads as hanging from the bar's edge. */
[data-site-bar] [data-slot="rail"] {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 2.25rem;
  padding: 3px;
  margin-inline-start: auto;
  border-radius: 6px 6px 12px 12px;
  background: var(--bar-sheen);
  box-shadow:
    inset 0 0 0 var(--bar-edge-width) var(--bar-velvet-line),
    var(--bar-glass-shadow);
}

/*
 * The velvet edge: a gradient painted over the whole border box, then masked down to a ring by
 * xor-ing the padding box out of it. A gradient cannot be a `border-color`, and `border-image`
 * does not follow `border-radius`, so the ring is the only way to get a sheen that turns the
 * corner. It takes no part in layout, so nothing moves when it appears.
 */
@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  [data-site-bar] [data-slot="rail"]::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    border-radius: inherit;
    padding: var(--bar-edge-width);
    background: var(--bar-velvet-edge);
    -webkit-mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
  }
}

/*
 * A rail link is a chip in a tray, not a button.
 *
 * `background`, `min-block-size` and `font-weight` are stated here because `[data-lift]` gives
 * every control it touches a button's resting box — an opaque fill, a 2.5rem minimum height and
 * semibold text — and a rail link that is filled at rest paints over the tray's own sheen and
 * stands taller than the 2.25rem tray it sits in. The contract's *response* is what these links
 * want; its resting geometry is not. The drawer rows next to them already said this, which is how
 * the omission here was found.
 */
[data-site-bar] [data-slot="link"] {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-block-size: 0;
  padding: 0 0.8rem;
  border: 1px solid transparent;
  border-radius: 3px 3px 9px 9px;
  background: transparent;
  color: var(--bar-ink);
  font-size: 0.9375rem;
  font-weight: inherit;
  white-space: nowrap;
  text-decoration: none;
}

/* The underline grows from the centre rather than appearing, which is what makes it read as a
   response to the pointer instead of a state change. It is laid out at its full length once and grown
   by a horizontal scale, so the growth is a transform rather than two edges laid out every frame. */
[data-site-bar] [data-slot="link"]::after {
  content: "";
  position: absolute;
  left: 0.8rem;
  right: 0.8rem;
  bottom: 3px;
  height: 2px;
  border-radius: 2px;
  background: var(--bar-hover-border);
  transform: scaleX(0);
  transition: transform 0.22s ease;
}

/*
 * Where the reader is, in the two ways there are to be somewhere.
 *
 * `aria-current="page"` is a console page: you are either on it or you are not. `data-current` is
 * the documentation, which is one destination covering hundreds of pages — Docs points at
 * `/intro/` rather than at whichever page is open, so claiming `page` there would announce the
 * wrong page to a screen reader. Both look the same; only one of them is a promise about the URL.
 */
[data-site-bar] [data-slot="link"]:is([aria-current="page"], [data-current]) {
  color: var(--bar-ink-strong);
  font-weight: 600;
}

[data-site-bar] [data-slot="link"]:is([aria-current="page"], [data-current])::after,
[data-site-bar] [data-slot="link"]:hover::after,
[data-site-bar] [data-slot="link"]:focus-visible::after {
  transform: none;
}

/*
 * The one hover pair the chrome swaps, named once for everything in the bar that navigates.
 *
 * There is no hover rule here. `interactive.css` owns what a hover does — the background becomes
 * the ink, the ink becomes the background, the border follows the ink, and the control lifts 2px —
 * and this only says which two colours the bar hands it.
 */
[data-site-bar] :is([data-slot="link"], [data-slot="sign-in"], [data-slot="menu-link"]) {
  --lift-surface: var(--bar-hover-fg);
  --lift-ink: var(--bar-hover-bg);
  --lift-line: var(--bar-hover-border);
}

/* --- actions -------------------------------------------------------------------------------- */

[data-site-bar] [data-slot="actions"] {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

[data-site-bar] [data-slot="sign-in"] {
  min-block-size: 0;
  padding: 0.5rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--bar-ink-strong);
  font-weight: inherit;
  white-space: nowrap;
  text-decoration: none;
}

/* --- the drawer ----------------------------------------------------------------------------- */

/*
 * Below 56rem the tray steps aside and the destinations move into a drawer.
 *
 * The two renderers open it differently and have to: the console has a button, a signal and a
 * focus trap, while the documentation's is a `<details>`, because the 404 page and the share pages
 * are static HTML that must navigate with JavaScript switched off. The panel they open is the same
 * panel, which is why only the opening is written twice.
 */
[data-site-bar] [data-slot="menu-toggle"] {
  display: none;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--bar-hairline);
  border-radius: 6px 6px 12px 12px;
  background: transparent;
  color: var(--bar-ink-strong);
  cursor: pointer;
}

[data-site-bar] [data-slot="menu-toggle"] path {
  transform-origin: 12px 12px;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

/*
 * Open, the two strokes meet in the middle and become the cross that closes it.
 *
 * Two ways of saying open, one rule: the console's shell carries `data-menu="open"` from its
 * signal, and the documentation's disclosure carries the `open` attribute `<details>` sets for
 * itself. Writing the transform once is the point of naming both here.
 */
[data-site-bar][data-menu="open"] [data-slot="menu-toggle"] [data-slot="top"],
[data-site-bar] [data-slot="menu-disclosure"][open] [data-slot="menu-toggle"] [data-slot="top"] {
  transform: translateY(4px) rotate(45deg);
}

[data-site-bar][data-menu="open"] [data-slot="menu-toggle"] [data-slot="bottom"],
[data-site-bar] [data-slot="menu-disclosure"][open] [data-slot="menu-toggle"] [data-slot="bottom"] {
  transform: translateY(-4px) rotate(-45deg);
}

/*
 * The `<details>` wrapper the documentation opens its drawer with. It is hidden above the drawer's
 * width, which is also what keeps a resize from leaving a panel open under a bar that has its tray
 * back — the console solves the same problem with its signal.
 *
 * Not `display: contents`: a `<details>` needs its own box for the open/closed rendering, and
 * removing it is how a disclosure quietly stops disclosing in some engines.
 */
[data-site-bar] [data-slot="menu-disclosure"] {
  display: none;
  position: relative;
}

/* The disclosure triangle is replaced by the two strokes above. */
[data-site-bar] [data-slot="menu-toggle"]::-webkit-details-marker {
  display: none;
}

[data-site-bar] summary[data-slot="menu-toggle"] {
  list-style: none;
}

[data-site-bar] [data-slot="menu"] {
  position: fixed;
  top: calc(var(--bar-shell-height) + 8px);
  inset-inline: 0.75rem;
  max-height: calc(100dvh - var(--bar-shell-height) - 24px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px;
  border-radius: 10px 10px 20px 20px;
  background: var(--bar-sheen), var(--bar-surface);
  box-shadow:
    inset 0 0 0 1px var(--bar-hairline),
    var(--bar-glass-shadow),
    var(--bar-velvet-glow);
  animation: site-bar-pop 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  font-size: 1rem;
}

[data-site-bar] [data-slot="menu-link"] {
  display: block;
  width: 100%;
  min-block-size: 0;
  padding: 14px;
  border: 0;
  border-radius: 6px 6px 12px 12px;
  background: transparent;
  color: var(--bar-ink-strong);
  font-weight: inherit;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}

[data-site-bar] [data-slot="menu-link"][aria-current="page"] {
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--bar-hover-border);
}

[data-site-bar] [data-slot="menu-actions"] {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--bar-hairline);
}

@keyframes site-bar-pop {
  from {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
  }
}

/* --- breakpoints ---------------------------------------------------------------------------- */

/* The tray and the sign-in link step aside for the drawer. */
@media (max-width: 56rem) {
  [data-site-bar] [data-slot="rail"],
  [data-site-bar] [data-slot="sign-in"] {
    display: none;
  }

  [data-site-bar] [data-slot="menu-disclosure"] {
    display: block;
  }

  [data-site-bar] [data-slot="menu-toggle"] {
    display: grid;
  }

  [data-site-bar] [data-slot="actions"] {
    margin-inline-start: auto;
  }
}

/*
 * The console renders its panel from a signal rather than from markup, so a resize can leave it
 * standing under a bar that has its tray back. Above the drawer's width there is no drawer.
 */
@media not all and (max-width: 56rem) {
  [data-site-bar] [data-slot="menu"] {
    display: none;
  }
}

@media (max-width: 30rem) {
  [data-site-bar] [data-slot="bar"],
  [data-site-bar] [data-slot="actions"] {
    gap: 0.5rem;
  }

  [data-site-bar] [data-component="brand-mark"] {
    height: 26px;
  }
}

/* --- footer --------------------------------------------------------------------------------- */

/*
 * The footer's link row, on both renderers. Where the footer sits and how it is framed is the
 * page's business — the console hangs it off the bottom of every marketing page behind a hairline,
 * the landing page closes its own framed hero with it — so only the row and the links are here.
 */
[data-site-footer] [data-slot="links"] {
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem 0.5rem;
  font-size: 0.875rem;
}

[data-site-footer] [data-slot="links"] a {
  min-block-size: 0;
  padding: 0.55rem 0.8rem;
  border: 1px solid transparent;
  border-radius: 6px 6px 12px 12px;
  background: transparent;
  color: var(--bar-ink-strong);
  font-weight: inherit;
  text-decoration: none;

  --lift-surface: var(--bar-hover-fg);
  --lift-ink: var(--bar-hover-bg);
  --lift-line: var(--bar-hover-border);
}

/* --- reduced motion ------------------------------------------------------------------------- */

/*
 * The colours still invert and the underline still arrives; only the travel goes. Someone who asks
 * for less motion is asking not to be moved, not to be left without the signal that a thing is
 * interactive. `interactive.css` makes the same promise for the lift itself.
 */
@media (prefers-reduced-motion: reduce) {
  [data-site-bar] [data-slot="link"]::after,
  [data-site-bar] [data-slot="menu-toggle"] path {
    transition: none;
  }

  [data-site-bar] [data-slot="menu"] {
    animation: none;
  }
}
/*
 * The master layout: site tokens, the shell the bar sits in, the theme toggle and the footer's frame.
 *
 * The bar itself is not here any more. Its tray, its links, its brand lockup, its drawer and its
 * breakpoints are @aicippy-code/ui/v2/styles/site-bar.css, which the documentation site loads too
 * (packages/web/src/components/Header.astro) — so there is one declaration of the bar instead of
 * two kept in step by hand. What is left here is this app's half of the wiring: the fixed shell,
 * which is our own `<header>` sized by `--site-header-h` where the documentation's is Starlight's
 * `header.header` sized by `--sl-nav-height`, and the `--bar-*` mapping below.
 *
 * Themes: light is the default and needs no attribute. Dark is `html[data-theme="dark"]`, set before
 * first paint by the boot script in entry-server.tsx: the reader's choice from the theme toggle, or
 * the system's `prefers-color-scheme` until they have made one (lib/theme.ts).
 */

:root {
  --site-header-h: 64px;
  --site-radius: 18px;

  /*
   * The column every marketing page and the bar above it share: 75rem of content, centred, with
   * one gutter on either side. The bar, the download, pricing, enterprise and account pages, the
   * legal documents, the changelog and the brand page all read these two, so the logo, Login and
   * the edges of the content below them sit on the same two lines on every page. They used to
   * differ by page -- 1136px of content on /download, 1152px on /account, 1200px on /pricing --
   * so the bar lined up with one of them at most.
   */
  --site-column: 75rem;
  --site-gutter: 1.5rem;

  /*
   * The chrome reads the same ink and the same lines as everything else. These names used to carry
   * their own values — a second, slightly cooler grey scale beside the page one — and
   * `--site-text-weak` in it measured 3.87:1 on the white card it is used on, which is what made the
   * sign-in card's body line and the labels on /account/billing look washed out. They are now views
   * on style/token/color.css, so every surface in the product inks the same way and a single edit
   * moves all of it. `color-scheme` and the document background live in style/, not here.
   */
  --site-surface: var(--surface-raised);
  --site-surface-sunk: var(--surface-sunken);
  --site-brand: #16256b;
  --site-text: var(--ink-body);
  --site-text-strong: var(--ink);
  --site-text-weak: var(--ink-muted);
  --site-hairline: var(--line);
  --site-line-strong: var(--line-strong);

  --site-glass-shadow: 0 1px 1px rgb(13 23 68 / 0.03), 0 10px 30px -18px rgb(13 23 68 / 0.18);
  --site-sheen-soft: linear-gradient(135deg, rgb(59 11 110 / 0.07), rgb(122 31 168 / 0.05) 55%, rgb(43 180 214 / 0.07));
  --site-velvet-glow: 0 8px 24px -16px rgb(21 6 38 / 0.5);

  --site-hover-bg: #1f0c3d;
  --site-hover-fg: #ffffff;
  --site-hover-border: #9a5fd0;

  /* One accent, the product's accent. See style/token/color.css. */
  --site-accent: var(--color-accent);
  --site-accent-hover: var(--color-accent-hover);
  --site-accent-fg: var(--color-primary-text);
  --site-focus: var(--color-accent);

  /*
   * This app's palette, handed to the shared site bar.
   *
   * site-bar.css names no colours of its own; it reads `--bar-*`. These aliases are the whole of
   * what this app has to say about how the bar looks, and brand.css says the same thing once for
   * the documentation. Two mappings, one appearance. Everything here already flips in the dark
   * block above, so there is nothing to repeat below it.
   *
   * One plain treatment for everything in the bar: the destinations, the theme toggle, Login and
   * the menu button are all unboxed until the pointer reaches them. The tray the destinations sat
   * in -- a sheen, a shadow and a dark velvet ring -- is switched off through the bar's own tokens;
   * beside a ringed square toggle and an unboxed Login it made three treatments in one bar.
   */
  --bar-ink: var(--site-text);
  --bar-ink-strong: var(--site-text-strong);
  --bar-brand: var(--site-brand);
  --bar-surface: var(--site-surface);
  --bar-hairline: var(--site-hairline);
  --bar-sheen: none;
  --bar-glass-shadow: 0 0 #0000;
  --bar-velvet-edge: none;
  --bar-velvet-line: transparent;
  --bar-velvet-glow: var(--site-velvet-glow);
  --bar-edge-width: 0px;
  --bar-hover-bg: var(--site-hover-bg);
  --bar-hover-fg: var(--site-hover-fg);
  --bar-hover-border: var(--site-hover-border);
  --bar-focus: var(--site-focus);
  --bar-shell-height: var(--site-header-h);
}

/* Starlight's bar is 3.5rem below 50rem, and both halves of the site are one bar. */
@media (max-width: 50rem) {
  :root {
    --site-header-h: 56px;
  }
}

@media (max-width: 40rem) {
  :root {
    --site-gutter: 1rem;
  }
}

/*
 * Every in-page jump clears the fixed bar: a link to #subscription, #terminal or a legal section
 * lands with its heading below the bar rather than underneath it.
 */
html {
  scroll-padding-top: calc(var(--site-header-h) + 1rem);
}

:root[data-theme="dark"] {
  /* Only what genuinely differs in the dark: the shadows, the sheen and the brand mark. The ink
     and the lines come from the one palette and have already flipped by the time we get here. */
  --site-brand: #ffffff;

  --site-glass-shadow: 0 1px 2px rgb(0 0 0 / 0.5), 0 16px 40px -20px rgb(0 0 0 / 0.8);
  --site-sheen-soft: linear-gradient(135deg, rgb(122 31 168 / 0.26), rgb(59 11 110 / 0.18) 55%, rgb(43 180 214 / 0.14));
  --site-velvet-glow: 0 12px 34px -18px rgb(122 31 168 / 0.55);

  --site-hover-bg: #f2eaff;
  --site-hover-fg: #150a26;
  --site-hover-border: #7a1fa8;
}

/* A theme switch cross-fades as one image instead of every surface transitioning on its own. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.28s;
}

[data-component="site"] {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

[data-component="site-main"] {
  flex: 1 0 auto;
  padding-top: var(--site-header-h);
  outline: none;
}

[data-component="skip-link"] {
  position: fixed;
  top: 0.75rem;
  inset-inline-start: 0.75rem;
  z-index: var(--z-skip-link);
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  background: var(--site-hover-bg);
  color: var(--site-hover-fg);
  font: 500 0.875rem/1.2 var(--font-sans);
  text-decoration: none;
  transform: translateY(-200%);
}

[data-component="skip-link"]:focus-visible {
  transform: none;
}

/* --- header --------------------------------------------------------------------------------- */

/*
 * Opaque, square and edged with a hairline, as the documentation draws its bar (brand.css). It used
 * to be 78% glass over a blur with a dark velvet ring and rounded bottom corners: text scrolling
 * underneath showed through it cut in half, and the ring read as a heavy dark rule across a light
 * page. The type is the page's sans, inherited; the size, the leading and the ink are the row's,
 * in site-bar.css.
 */
[data-component="site-header"] {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--site-header-h);
  background: var(--site-surface);
  border-bottom: 1px solid var(--site-hairline);

  /* This shell holds controls of its own -- the theme toggle, the avatar, the account menu -- that
     the shared bar knows nothing about, so the type and ink reset stays here. The focus ring does
     not: site-bar.css draws one for everything in the bar, including these. */
  a,
  button {
    font: inherit;
    color: inherit;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
}

/* The bar's contents share the pages' column, so on a wide screen the logo and the actions line
   up with the content below instead of drifting to the far edges. The row itself — its flex, its
   gap, its type — is site-bar.css; only the column is this app's. The documentation's landing page
   takes the same column (packages/web/src/components/Header.astro). */
[data-component="site-header"] [data-slot="bar"] {
  max-width: calc(var(--site-column) + 2 * var(--site-gutter));
  margin: 0 auto;
  padding-inline: var(--site-gutter);
}

/* The menu button is unboxed like the theme toggle beside it; site-bar.css gives it a ring. */
[data-component="site-header"] [data-slot="menu-toggle"] {
  border-color: transparent;
  border-radius: 8px;
  color: var(--bar-ink-strong);
}

[data-component="site-header"] [data-slot="menu-toggle"]:hover {
  background: var(--site-hover-bg);
  border-color: var(--site-hover-border);
  color: var(--site-hover-fg);
}

/* --- theme toggle --------------------------------------------------------------------------- */

/* Unboxed at rest, like every other control in the bar, and inverted under the pointer. The
   documentation's toggle is the same box (packages/web/src/components/ThemeSelect.astro). */
[data-component="theme-toggle"] {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--site-text-strong);
  cursor: pointer;
  transition:
    background-color 0.18s ease,
    border-color 0.18s ease,
    color 0.18s ease;

  svg {
    overflow: visible;
  }

  [data-slot="body"],
  [data-slot="bite"] {
    transform-box: view-box;
    transform-origin: 12px 12px;
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }

  [data-slot="rays"] {
    transform-box: view-box;
    transform-origin: 12px 12px;
    transition:
      transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
      opacity 0.3s ease;
  }
}

[data-component="theme-toggle"]:hover,
[data-component="theme-toggle"]:focus-visible {
  background: var(--site-hover-bg);
  border-color: var(--site-hover-border);
  color: var(--site-hover-fg);
}

/* Dark: the disc grows, a bite slides in to carve the crescent, and the rays turn away. */
:root[data-theme="dark"] [data-component="theme-toggle"] {
  [data-slot="body"] {
    transform: scale(1.7);
  }

  [data-slot="bite"] {
    transform: translate(-7.5px, 3.5px);
  }

  [data-slot="rays"] {
    opacity: 0;
    transform: rotate(-90deg) scale(0.4);
  }
}

/* --- account -------------------------------------------------------------------------------- */

[data-component="site-header"] [data-slot="account"] {
  position: relative;
  display: flex;
  align-items: center;
}

/*
 * Login is drawn from the first paint, because the server renders the session as still loading and
 * nearly every visitor is signed out. Only a tab that holds a token (`data-session`, set before
 * paint by SESSION_HINT_SCRIPT in lib/session.ts) keeps the slot quiet until the avatar arrives, so
 * a signed-in reader never sees Login flash first.
 */
:root[data-session="stored"] [data-component="site-header"] [data-slot="account"][data-status="loading"] [data-slot="sign-in"] {
  visibility: hidden;
}

[data-component="site-header"] [data-slot="avatar"] {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, #3b0b6e 0%, #7a1fa8 55%, #2bb4d6 140%);
  color: #ffffff;
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
}

[data-component="site-header"] [data-slot="account-menu"] {
  position: absolute;
  top: calc(100% + 10px);
  inset-inline-end: 0;
  min-width: 15rem;
  max-width: min(20rem, calc(100vw - 2rem));
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-radius: 8px 8px 16px 16px;
  background: var(--site-sheen-soft), var(--site-surface);
  box-shadow: inset 0 0 0 1px var(--site-hairline), var(--site-glass-shadow), var(--site-velvet-glow);
  animation: site-bar-pop 0.18s cubic-bezier(0.22, 1, 0.36, 1);

  /*
   * The actionable items live in their own `role="menu"` element, because the identity block above
   * them is not a menu item and ARIA does not allow it inside one. `display: contents` keeps the
   * panel's own flex column exactly as it was, however many items the menu grows to.
   */
  [data-slot="account-menu-items"] {
    display: contents;
  }

  /*
   * Which workspace the person is acting in. Present only for somebody who belongs to at least one
   * organisation, so most accounts never see it and the menu keeps the height it always had.
   */
  [data-slot="workspace-switcher"] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 4px 0 6px;
    border-bottom: 1px solid var(--site-hairline);
    margin-bottom: 4px;

    [data-slot="workspace-label"] {
      padding: 2px 12px 4px;
      font-size: 0.72rem;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      color: var(--site-ink-faint, inherit);
      opacity: 0.7;
    }

    button {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 12px;
      width: 100%;
      text-align: start;
    }

    /* The grant is the part that surprises people: an owner of their own workspace may be only a
       viewer of an employer's. It is quiet, but it is always there. */
    [data-slot="workspace-grant"] {
      font-size: 0.72rem;
      letter-spacing: 0.03em;
      opacity: 0.6;
      flex: none;
    }

    button[data-selected="true"] [data-slot="workspace-name"] {
      font-weight: 600;
    }
  }

  [data-slot="identity"] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px 12px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--site-hairline);
    line-height: 1.3;
    overflow-wrap: anywhere;

    strong {
      color: var(--site-text-strong);
      font-weight: 600;
    }

    span {
      color: var(--site-text-weak);
      font-size: 0.8125rem;
    }
  }

  a,
  button {
    display: block;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    border-radius: 6px 6px 10px 10px;
    background: transparent;
    color: var(--site-text-strong);
    text-align: start;
    cursor: pointer;
  }

  a:hover,
  a:focus-visible,
  button:hover,
  button:focus-visible {
    background: var(--site-hover-bg);
    color: var(--site-hover-fg);
  }
}

/*
 * There is no subscribe button in this header, on any screen and for any visitor. Selling belongs
 * to the pricing page and to the invitation in `agent-nudge.css`, which never reaches a subscriber.
 * The rules that styled `[data-slot="cta"]` and `[data-slot="menu-cta"]` went with the markup.
 */

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

/*
 * The drawer itself — the toggle, the panel it opens, the rows inside it and the breakpoint that
 * brings all three on — is site-bar.css. Only the two things below are this app's: the page behind
 * the open panel stops scrolling, which needs the signal the header component sets, and the empty
 * account wrapper leaves the row.
 */
:root[data-site-menu="open"] {
  overflow: hidden;
}

@media (max-width: 56rem) {
  /*
   * Signed out or still deciding, the account wrapper's only child is the hidden sign-in link — an
   * empty flex item that still claims a 0.75rem gap on either side of itself. That was invisible
   * behind the subscribe button; with the button gone it is a hole between the theme toggle and the
   * menu toggle, so the empty wrapper leaves the row rather than holding a place for nothing.
   */
  [data-component="site-header"] [data-slot="account"]:not([data-status="signed-in"]) {
    display: none;
  }
}

/* --- footer --------------------------------------------------------------------------------- */

[data-component="site"] [data-component="site-footer"] {
  margin-top: 4rem;
  border-top: 1px solid var(--site-hairline);
  font-size: 0.875rem;
  color: var(--site-text);

  /* The column and where it sits. The row inside it, and the shape and hover of each link, are
     site-bar.css -- the same row the landing page closes itself with. */
  /* One footer, two lines -- not two footers.
     The gap between the destinations and the signature below them used to be 2rem of padding on
     each, which read as two separate blocks stacked on top of each other. They are one closing
     mark: the row of places to go, then the line that signs it. Tightened so they group. */
  [data-slot="links"] {
    max-width: calc(var(--site-column) + 2 * var(--site-gutter));
    margin: 0 auto;
    padding: 2.25rem var(--site-gutter) 0.75rem;
  }

  [data-component="legal"] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.4rem 1.5rem;
    padding: 0 var(--site-gutter) 2.25rem;
    font-size: 0.8125rem;
    color: var(--site-text-weak);
    text-align: center;
  }

  [data-component="legal"] a {
    color: var(--site-text-weak);
    text-decoration: none;
  }

  [data-component="legal"] a:hover {
    color: var(--site-text-strong);
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /*
   * Only what this file still draws. The bar's transitions are site-bar.css's to stop and the lift
   * is the interaction contract's, and both already do -- while keeping the colour change, which is
   * the part that tells a reader a control is interactive. A blanket `transition: none !important`
   * across the whole header and footer used to sit here and took that signal away with the motion.
   */
  [data-component="theme-toggle"] *,
  [data-component="site-header"] [data-slot="account-menu"] {
    transition: none !important;
    animation: none !important;
  }

  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}
