@layer components {
  /* The panel toggles sit at the ends of the page nav; when a panel opens, its
     toggle leaves the nav's flex flow and anchors to the panel's top corner.
     The fixed header is the containing block, so the negative inset lands 1ch
     inside the viewport edge — and because the header's inline insets animate
     with the same curve as the panel slide, the keycap rides the panel's
     corner through both transitions. */
  :is(.sidebar__toggle, .dock__toggle) {
    align-items: center;
    color: var(--color-ink);
    cursor: pointer;
    display: inline-flex;
    gap: 0.5ch;
    transition:
      inset-inline-start 0.2s ease-out,
      inset-inline-end 0.2s ease-out,
      color 0.2s ease-out;
    z-index: 1;

    input[type="checkbox"] {
      display: none;
    }

    @media (max-width: 70ch) {
      display: none;
    }
  }

  :has(#sidebar-toggle:checked) .sidebar__toggle,
  :has(#dock-toggle:checked) .dock__toggle {
    color: var(--color-red);

    @media (min-width: 70ch) {
      position: absolute;
    }
  }

  @media (min-width: 70ch) {
    :has(#sidebar-toggle:checked) .sidebar__toggle {
      inset-block-start: calc(var(--block-space-half) + 0.2rem);
      inset-inline-start: calc(var(--inline-space) - var(--sidebar-width));
    }

    :has(#dock-toggle:checked) .dock__toggle {
      /* Centre on the header bar: half the slack between the bar and the
         keycap (1.4em at the keycap font). */
      inset-block-start: calc((var(--header-height) - 1.4 * var(--keycap-font-size)) / 2);
      inset-inline-end: calc(var(--inline-space) - var(--dock-width));
    }
  }

  /* The toggles read as a quiet panel icon; the letter beside it — revealed by
     Shift — is a miniature of the house keycap (base.css kbd): currentColor
     border plus the 0.1em bottom-edge shadow, so it tints muted at rest, ink
     on hover and dock-red when open, all through inheritance. The outer kbd is
     just the layout capsule. */
  :is(.sidebar__toggle, .dock__toggle, .dock__wide-toggle, .dock__full-toggle, .palette__toggle, .timeline__toggle, .help__toggle, .avatar-menu__trigger) kbd {
    /* Center, not baseline: the mini keycap is a bordered box beside a larger
       icon, so it should sit on the icon's optical middle. */
    align-items: center;
    border: 0;
    box-shadow: none;
    color: var(--color-ink-muted);
    display: inline-flex;
    font-size: var(--keycap-font-size);
    gap: 0.3ch;
    line-height: 1;
    opacity: 1;
    /* Tight inline padding: the reserved (invisible) keycaps already space the
       toggles apart; generous padding on top read as gaps in the header. */
    padding: 0.2em 0.25em;
    transition: color 0.15s ease;
  }

  /* The timeline clock and help mark are link-blue actions; only the
     revealed keycap letter rides the kbd's muted-to-ink ride. */
  :is(.timeline__toggle, .help__toggle) kbd i {
    color: var(--color-blue);
    transition: color 150ms ease;
  }

  :is(.timeline__toggle, .help__toggle):hover kbd i {
    color: var(--color-blue-bright);
  }

  .timeline__toggle {
    align-items: center;
    display: inline-flex;
  }

  /* Basecamp-style hint reveal: every shortcut fires with Shift, and holding
     Shift is also what shows the letters — hotkey-mode flips one attribute on
     <body>, CSS does all the showing. No letters on touch or narrow screens,
     where there is no Shift to hold. */
  .key-letter {
    display: none;
    border: 1px solid currentColor;
    border-radius: 0.3em;
    box-shadow: 0 0.1em 0 currentColor;
    /* Rides the kbd font so the cap shrinks with its icon on smaller screens;
       floored at legibility. ~0.65rem beside the full-size header icons. */
    font-size: max(0.55rem, 0.46em);
    font-weight: 600;
    line-height: 1;
    padding: 0.15em 0.4em;
    /* Optical: the solid bottom-edge shadow adds visual mass below the
       flex-centred box, so the cap reads low — lift it by half the shadow. */
    translate: 0 -0.05em;
  }

  /* Underlined hosts (.link triggers) draw their text-decoration straight
     through blockified flex children, and the child cannot cancel a propagated
     decoration — but propagation skips the contents of atomic inlines, so the
     letter lives in an inner span (rendered by the key_letter helper). */
  .key-letter > span {
    display: inline-block;
  }

  /* The avatar's U keycap has no icon inside — hide the whole capsule, or its
     empty padding box would linger beside the avatar. */
  .avatar-menu__trigger kbd {
    display: none;
  }

  /* Shift toggles the keycaps into the flow wherever a keyboard is likely
     (hover-capable screens, any width) — the bars may reflow; only the
     absolutely-centred breadcrumbs are guaranteed still. Touch devices never
     see the caps. */
  @media (any-hover: hover) {
    /* :where keeps the reveal's specificity below composite hiders like
       .btn--collapse's icon-only state, which must win while collapsed. */
    body[data-hotkey-mode] :where(.key-letter) {
      display: inline-block;
    }

    body[data-hotkey-mode] .avatar-menu__trigger kbd {
      display: inline-flex;
    }
  }

  :is(.sidebar__toggle, .dock__toggle, .dock__wide-toggle, .dock__full-toggle, .palette__toggle, .timeline__toggle, .help__toggle, .avatar-menu__trigger):is(:hover, :has(input:checked)) kbd,
  .dock__full-toggle--active kbd {
    color: inherit;
  }

  /* The resize + fullscreen keycaps sit at the dock's inner (left) edge —
     widening pulls that edge outward. One positioned flex row holds both so they
     share the header's line; the controls inside are static. */
  .dock__controls {
    align-items: center;
    display: inline-flex;
    gap: 0.5ch;
    /* Same centring as the main J toggle, so both rows share the header's
       vertical middle. */
    inset-block-start: calc((var(--header-height) - 1.4 * var(--keycap-font-size)) / 2);
    inset-inline-start: var(--inline-space);
    position: absolute;
    /* Above the dock content, whose nav box transparently overlaps this corner
       and would swallow hover and clicks. */
    z-index: 1;
    /* Match the main J toggle's keycap height (main font 1.4rem max × line-height
       1 + 0.4em padding = 1.4em) so the smaller secondary keycaps centre on the
       same axis as the main toggle instead of top-aligning a couple px higher. */
    min-block-size: calc(1.4 * var(--keycap-font-size));
  }

  .dock__wide-toggle,
  .dock__full-toggle {
    align-items: center;
    color: var(--color-ink);
    cursor: pointer;
    display: inline-flex;

    input[type="checkbox"] {
      display: none;
    }
  }

  /* These are secondary controls beside the main J toggle — a notch smaller so
     the dock toggle stays the primary mark. Padding/gap are em-based, so scaling
     the font shrinks the whole keycap proportionally. */
  .dock__controls kbd {
    font-size: clamp(0.85rem, 2.1vi, 1.2rem);
  }

  .dock__controls:has(#dock-wide:checked) .dock__wide-toggle,
  .dock__full-toggle--active {
    color: var(--color-red);
  }

  body.app:has(#dock-wide:checked) {
    --dock-width: 45vw;
  }

  /* The dock is a size container, so .btn--collapse — which keys off the
     viewport — never collapses inside a narrow dock on a wide screen. Mirror the
     collapse against the dock's own inline size so labelled actions (e.g. Neues
     Handbuch) shrink to their icon here too. */
  @container (max-width: 30rem) {
    #dock .btn--collapse {
      --btn-padding: 0;
      --btn-collapse-size: calc(1lh + 2 * var(--block-space-quarter) + 4px);

      display: inline-grid;
      place-items: center;
      inline-size: var(--btn-collapse-size);
      block-size: var(--btn-collapse-size);
    }

    #dock .btn--collapse > :not(i):not(.for-screen-reader) {
      display: none;
    }
  }

  /* The dock is a utility surface: reading columns open up to the panel edge
     (the panel width is the measure) and prose drops a notch under the app's
     primary size. The full handbook page keeps the website reading treatment. */
  #dock .content-width-reading {
    inline-size: 100%;
  }

  #dock .prose {
    font-size: var(--font-small-responsive);
  }

  /* Tenant rail: the dock is a small stack of coexisting surfaces, each in its
     own permanent frame, so switching tenants never loses state. Hidden while
     only the resident tenant exists — it appears once a preview lands in the
     ephemeral slot. */
  .dock__rail {
    align-items: center;
    display: flex;
    gap: var(--inline-space);
    margin-block-end: var(--block-space);
  }

  #dock:has(#dock_preview:empty) .dock__rail {
    display: none;
  }

  .dock__tab {
    align-items: center;
    color: var(--color-ink-muted);
    cursor: pointer;
    display: inline-flex;
    font-size: var(--font-small-responsive);
    gap: 0.5ch;

    input[type="radio"] {
      display: none;
    }

    &:hover,
    &:has(input:checked) {
      color: var(--color-ink);
    }

    &:has(input:checked) {
      font-weight: 500;
      text-decoration: underline;
      text-decoration-thickness: 0.15em;
      text-underline-offset: 0.5em;
    }
  }

  .dock__tab-group {
    align-items: center;
    display: inline-flex;
    gap: 0.5ch;
  }

  .dock__tab-close {
    color: var(--color-ink-muted);

    &:hover {
      color: var(--color-ink);
    }
  }

  /* The checked radio picks the visible frame. The empty slot never wins:
     while a preview is still loading, handbooks stays up and the swap happens
     only when content lands — no blank flash. */
  #dock:has(#dock-tenant-preview:checked):not(:has(#dock_preview:empty)) #dock_content {
    display: none;
  }

  #dock:has(#dock-tenant-handbooks:checked) #dock_preview,
  #dock_preview:empty {
    display: none;
  }

  /* No sticky header overlaps the dock's own scroller — anchored headings only
     need a breath of headroom here, not the full-page header clearance. */
  #dock .prose :is(h1, h2, h3)[id] {
    scroll-margin-block-start: var(--block-space);
  }

  /* Native Fullscreen API lifts #dock to the browser's top layer at 100vw — the
     grid, header and sidebar are untouched (they're simply not painted). This
     block is purely cosmetic: the header-clearing offsets no longer apply (no
     header), and the reading column re-centers so a handbook doesn't run
     edge-to-edge. Zero interaction with --dock-width or the grid. */
  #dock:fullscreen {
    margin-block-start: 0;
    /* Clear the absolutely-positioned ⇧F keycap (its inset + height ≈ 2.2rem) so
       the first line of content isn't tucked under it. */
    padding-block-start: var(--block-space-double);

    /* Widening is meaningless in fullscreen (no grid to widen into) — leave only
       the ⇧F exit control. */
    .dock__wide-toggle {
      display: none;
    }

    .content-width-reading {
      inline-size: min(clamp(38.3rem, 95.8cqi, 53.65rem), 100%);
      margin-inline: auto;
    }

    .prose {
      font-size: clamp(1rem, 2.5cqi, 1.4rem);
    }
  }


  /* Search input sits IN the dock's grey ground instead of popping as a bright
     white card. A hair lighter than the ground reads as a gently recessed field;
     the whole group shares one fill so the icon side no longer looks bolted on.
     Derived from the ground colour, so it tracks light/dark automatically. */
  #dock .input-group {
    background-color: color-mix(in oklch, var(--color-gray-light), var(--color-bg) 55%);
    border-color: color-mix(in oklch, var(--color-ink) 10%, transparent);
  }

  #dock .input-group .form__input,
  #dock .input-group__append {
    background-color: transparent;
  }
}
