/**
 * Share dock — canonical shared component `.tr-share-dock`. (SHARE-01)
 * ----------------------------------------------------------------------------
 * ONE stylesheet for every post type. There is no tool-share-dock.css,
 * prompt-share-dock.css or glossary-share-dock.css and there must not be — the
 * dock is byte-identical on all twelve single views, and the only thing that
 * varies is the URL and title inside it, which is a PHP concern
 * (see inc/share-dock.php).
 *
 * TOKEN-PURE. Every colour, space, radius, shadow, size, weight and duration
 * below is a `var()`. There is not one hex literal, not one raw colour, and not
 * one hardcoded z-index — the stack comes from the `--z-*` scale in
 * theme-unified.css (CLAUDE.md §9.5).
 *
 * DARK AND LIGHT COME FOR FREE. Nothing here is scoped to `[data-theme="dark"]`.
 * Every surface resolves through `--surface-base`, `--border-default` and
 * `--color-text-*`, all already paired in the token layer, so the dock inverts
 * with the page and cannot drift from it. A theme-scoped block here would be a
 * second place to keep in sync.
 *
 * THE MOBILE/TABLET GATE LIVES HERE AND NOWHERE ELSE. The server cannot know a
 * viewport without sniffing the user agent, which would make every single view
 * uncacheable; the runtime deliberately has no width opinion either, so the two
 * cannot disagree at one pixel. One media query is the whole gate.
 *
 * NO FOCUS RING IS DECLARED. theme-unified.css ships a global
 * `*:focus-visible` ring; re-stating it here would be a second definition to
 * keep in sync, and overriding it would be a WCAG 2.4.7 regression.
 *
 * @package TiorAI
 * @since 4.10.0
 */

/* ============================================================================
   THE GATE — phone and tablet only
   ============================================================================
   `1024 / 1025` is one of the theme's canonical complement pairs (CLAUDE.md
   A-13). Everything in this file lives inside this query, so on a desktop
   viewport the dock is not merely hidden — it has no rules at all, and the
   markup in the footer costs one `display: none` from the `[hidden]`-free
   default below.

   The whole component is declared `display: none` outside the query rather than
   inside it, so that the OFF state is the one that needs no media support. */

.tr-share-dock {
  display: none;
}

@media (max-width: 1024px) {

  /* ==========================================================================
     ROOT
     ========================================================================== */

  /*
   * The root spans the viewport but CATCHES NOTHING.
   *
   * `pointer-events: none` here with `auto` on the pill and the sheet is what
   * keeps a full-width fixed layer from stealing taps from the article
   * underneath it. Without it the dock would swallow every touch in a 72px band
   * across the bottom of the page — including on the links and buttons that the
   * single templates put there.
   */
  .tr-share-dock {
    display: flex;
    flex-direction: column;

    /*
     * CENTRED, and a WIDE bar rather than a compact corner pill.
     *
     * This is the second position the dock has had. It was built centred, moved
     * to the inline-end corner when browser QA found it crossing the sticky
     * `.tr-section-nav`, and moved back here on request — with the nav collision
     * now solved properly by `trackSectionNav()` in the runtime rather than by
     * hiding from it in a corner, which is the better fix anyway.
     *
     * The bar is `80%` of the viewport (see `__pill` below), so it reads as a
     * deliberate action bar rather than a floating chip, and it has room for the
     * vote control the Tool single puts inside it.
     */
    align-items: center;
    gap: var(--space-2);

    position: fixed;
    inset-inline: 0;

    /*
     * SAFE AREA. On an iPhone the home indicator occupies the bottom ~34px of
     * the viewport, and a control placed at `bottom: 0` sits underneath it —
     * reachable in theory, and a coin-flip in practice. `env()` resolves to 0px
     * on every device without one, so the fallback needs no query.
     *
     * The space token is ADDED to the inset rather than replaced by it, so the
     * dock keeps its own breathing room on a device that has no notch.
     */
    /*
     * `--tiorai-share-dock-lift` is 0 except while the sticky section nav is
     * resting in this band, when TiorAI.ShareDock sets it to that nav's measured
     * height. The DEFAULT is the whole contract: with the script blocked the
     * fallback keeps the dock exactly where it is, and nothing about the
     * component's resting position depends on JavaScript having run.
     */
    bottom: calc(
      var(--space-4) +
      env(safe-area-inset-bottom, 0px) +
      var(--tiorai-share-dock-lift, 0px)
    );

    /*
     * NO TRANSITION ON `bottom`, deliberately, and this cost a measured bug to
     * learn. An eased lift looks better standing still and is wrong in motion:
     * the lift TRACKS A SCROLLING ELEMENT, so easing puts the pill in
     * intermediate positions the geometry never asked for. Measured on the
     * comparison single at 390px, sweeping 19 scroll positions with
     * `transition: bottom 0.18s ease`: the pill was caught mid-ease at scroll
     * 100, sitting at 760-806 while its resting band is 782-828 — inside the
     * nav's box, which is the exact overlap the lift exists to prevent. With the
     * transition removed the same sweep is clean at every sample.
     *
     * The component therefore animates NOTHING positional. The only transitions
     * left are the two colour fades on the controls.
     */

    pointer-events: none;

    /*
     * `--z-sticky` (200), the same rung the site header takes. The header is at
     * the top of the viewport and this is at the bottom, so the two cannot
     * overlap; sharing a rung is what keeps a later dropdown (`--z-dropdown`,
     * 100) below both and every modal (`--z-modal`, 500) above both.
     *
     * Audited before choosing: no other component in the theme is bottom-docked
     * on a single view. `.workflow-toast` is bottom-RIGHT and only on a post
     * type with no published posts; `.news-toast` is top-right; `.tr-progress`
     * is a 2px line under the header; `.tools-offcanvas` is the tools ARCHIVE
     * filter drawer. Nothing to collide with, and no arbitrary z-index needed
     * to win a fight that does not exist.
     */
    z-index: var(--z-sticky);
  }

  /* ==========================================================================
     THE PILL
     ========================================================================== */

  /*
   * 92% of the viewport, capped at 310px, centred.
   *
   * The two numbers do different jobs and that is why there are two. The cap is
   * what the bar actually wants to be: four controls need about 300px and no
   * more, so on any viewport wide enough it settles there and stops — a 700px
   * bar on a tablet would be a strip of empty ground with four buttons in it.
   * The percentage only governs the phones NARROWER than the cap, where it keeps
   * a comfortable margin either side instead of touching the edges.
   *
   * At 375px the percentage binds (345 → capped to 310); at 320px it binds
   * properly (294px, 13px of air each side); from ~337px up the cap binds.
   *
   * `space-evenly` distributes whatever the bar is carrying — two controls on
   * most post types, four on `ai_tool` — so both read as a deliberate action bar
   * rather than as a short pill someone stretched.
   */
  .tr-share-dock__pill {
    display: flex;
    align-items: center;

    /*
     * THE BAR IS AS WIDE AS WHAT IT CARRIES, up to a cap. Not a fixed width with
     * the contents distributed inside it.
     *
     * Two measurements drove this. With a fixed 310px and `space-evenly`, the
     * three groups occupied 291px and left 19px to share across four slots —
     * 4px gaps, a bar that was FULL rather than distributed, and that is what
     * read as cramped. Switching to `space-between` fixed the Tool single and
     * broke everything else: on a post type with no vote control there are only
     * two groups, so Share was pinned hard left and Copy hard right with a
     * ~120px hole between them.
     *
     * `fit-content` removes the whole problem instead of tuning it. The bar
     * measures its contents and stops: ~281px on the Tool single with the vote
     * control, ~167px on a Glossary term without it, both centred, both with the
     * same honest `gap` between groups. No configuration, no counting children,
     * and a future control added to the bar widens it by exactly its own width.
     *
     * The cap is `min()` of the two limits so both still apply — 310px is what
     * four controls want, and 92% is what keeps a margin on a phone narrower
     * than that.
     */
    justify-content: center;
    gap: var(--space-4);
    inline-size: fit-content;
    max-inline-size: min(92%, 310px);

    /*
     * The controls are 44px and the bar was 46px, so they sat 1px from a
     * 9999px-radius edge — visually touching it at the corners. A 4px band
     * top and bottom is what lets a pill contain a pill.
     */
    padding-block: var(--space-1);
    padding-inline: var(--space-2);

    background: var(--surface-base);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-full);
    box-shadow: var(--shadow-lg);

    pointer-events: auto;

    /*
     * The pill clips its own children so the buttons' hover and active surfaces
     * follow the rounded edge instead of squaring off the ends.
     */
    overflow: hidden;
  }

  .tr-share-dock__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);

    /*
     * 44px. The WCAG 2.5.5 / platform-guidance minimum for a touch target, and
     * the height the theme's own `.btn` already uses — so the dock's controls
     * are not a smaller tap target than every other button on the page.
     */
    min-block-size: 44px;
    min-inline-size: 44px;
    padding-inline: var(--space-4);

    margin: 0;
    border: 0;
    background: transparent;
    color: var(--color-text-primary);

    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: 1;

    cursor: pointer;

    /* Colour only. Nothing here animates a box or a position, so the dock can
       never be the cause of a layout shift. */
    transition: background-color 0.15s ease, color 0.15s ease;
  }

  .tr-share-dock__btn:hover {
    background: var(--surface-selected);
    color: var(--color-primary);
  }

  .tr-share-dock__btn--share {
    /* The primary action reads as the primary action. Brand colour on the label
       rather than a filled pill, because a solid brand slab floating over the
       article is louder than a share affordance has any need to be. */
    color: var(--color-primary);
  }

  /*
   * Both dock controls give back the padding they were carrying for edge
   * clearance — the pill's own `padding-inline` does that job now, and every
   * pixel they release becomes gap between the groups instead of dead space
   * inside them. The 44px target is untouched: it comes from `min-block-size`
   * and `min-inline-size`, not from this padding.
   */
  .tr-share-dock__btn--share,
  .tr-share-dock__btn--copy {
    padding-inline: var(--space-3);
  }

  .tr-share-dock__icon {
    display: inline-flex;
    flex: none;
  }

  /* ==========================================================================
     THE VOTE CONTROL, WHEN THE POST TYPE VOTES
     ==========================================================================
     PLACEMENT, PLUS ONE FRAME RULE. The widget's own pill frame is dissolved so
     the bar does not render a pill inside a pill, its question is hidden, its
     error channel is capped, and each button's border is removed. Nothing else:
     no colour, no icon, no count style, no pressed state, no hover. Those belong
     to assets/css/unified/vote.css and a change there reaches this bar for free.

     THE SCOPE IS WHAT MAKES THIS SAFE. Every selector is rooted at
     `.tr-share-dock__pill >`, so none of it can reach a `.tr-vote` anywhere else
     — and the Tool single renders one in its own column, which keeps the
     component's default skin exactly. Verified by measuring both widgets on the
     same page.

     Same scoped-placement pattern as `.tr-cmp__rail > .tr-share-card` in the
     comparison module. */

  .tr-share-dock__pill > .tr-vote {
    /* Frame dissolved — the bar is already the frame. */
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;

    /* It is a group inside a row, not a row of its own: no wrapping, and no
       growing past the space its buttons need. */
    flex: none;
    flex-wrap: nowrap;
    gap: var(--space-2);
    padding-inline: var(--space-3);
  }

  /*
   * NO PER-BUTTON FRAME inside the bar — and NOTHING ELSE.
   *
   * `.tr-vote__btn` is a bordered rounded chip. That is right in a page column,
   * where it has to look like a control standing on open ground; it is wrong
   * here, where it already sits inside a bordered rounded bar and the pill's own
   * frame does that job for every control in the row. Share and Copy carry no
   * chrome either, so with the border gone the four read as one set.
   *
   * THE BORDER IS THE WHOLE OVERRIDE, and getting here took removing three rules
   * that should never have been written:
   *
   *   - Icon colours. The component already paints green up / red down at rest
   *     (`.tr-vote__btn--up svg`), so restating them here was duplicating a
   *     decision that has an owner. It only LOOKED missing because the browser
   *     was serving a stale `vote.css` from the `?ver` cache — a measurement
   *     artefact, read as a gap in the component.
   *
   *   - A voted ground of `--color-success-light` / `--color-danger-light`.
   *     Those tokens are theme-INVARIANT (#d1fae5 / #fee2e2), so on the dark bar
   *     they painted an opaque pale mint block. Measured: `rgb(209, 250, 229)`
   *     on `rgb(7, 11, 18)`. `vote.css` carries a comment warning against
   *     exactly this and uses translucent `rgba()` tints that composite over
   *     whatever ground they land on; deleting the override restores them.
   *
   *   - `min-block-size: 44px`. The component already pins 44px in both axes.
   *
   * The lesson worth keeping: read the component before overriding it, and
   * verify the read is not a cached file.
   */
  .tr-share-dock__pill > .tr-vote .tr-vote__btn {
    border-color: transparent;
    padding-inline: var(--space-2);
  }

  /*
   * NO RING ON THE VOTED CONTROL, inside the bar only.
   *
   * `.tr-vote__btn--voted` draws `box-shadow: inset 0 0 0 1px currentColor` — a
   * hairline ring. On a page column, where the button also has a real border, it
   * reads as that border thickening. In the bar the border is gone, so the ring
   * is the ONLY round line on the control and it reads as a stray circle drawn
   * around one thumb.
   *
   * WHAT STILL CARRIES THE VOTED STATE, so this is not colour-alone
   * (CLAUDE.md §9.11): the tinted ground `rgba(22, 163, 74, 0.18)`, the
   * `font-weight: 700` on the count, and `aria-pressed="true"`. Three signals,
   * one of them non-visual.
   *
   * The ring is RESTORED under forced-colors below — that is the one mode where
   * the tint is discarded and the ring becomes the only thing left.
   */
  .tr-share-dock__pill > .tr-vote .tr-vote__btn--voted {
    box-shadow: none;

    /*
     * AND NO TINTED GROUND EITHER. Removed on request, after the ring above:
     * with the button already 44px wide and `radius-full`, a filled ground is a
     * solid disc, which is the same shape objection the ring was.
     *
     * Applied to BOTH directions, not just the upvote that prompted it. Leaving
     * the downvote with a red disc while the upvote had none would read as a
     * rendering bug rather than as a decision.
     *
     * WHAT DISTINGUISHES A VOTED CONTROL NOW: `font-weight: 700` on the count
     * (from `.tr-vote__btn--voted`, and the reason that rule is not overridden
     * here) and `aria-pressed="true"`. Both survive; neither is colour, so this
     * does not become a "colour alone" failure under WCAG 1.4.1 — the resting
     * and voted controls differ by weight, not hue. It IS subtler than the tint
     * was, which is the trade being made deliberately.
     *
     * The `forced-colors` block still restores a ring, because weight alone is
     * not enough when author colours are discarded.
     */
    background: none;
  }

  /*
   * The question is hidden, not removed.
   *
   * There is no room for a sentence in a 56px bar. It stays in the DOM because
   * `display: none` on a `<span>` whose siblings are self-labelled buttons costs
   * a screen reader nothing — `.tr-vote__btn` carries its own `aria-label`
   * ("Upvote" / "Downvote"), so the control is fully described without it.
   */
  .tr-share-dock__pill > .tr-vote > .tr-vote__label {
    display: none;
  }

  /*
   * The widget's error channel is `flex-basis: 100%`, so inside the widget it
   * drops onto its own line. In a single-line bar that would force the whole row
   * to wrap the moment a vote failed.
   *
   * It stays IN FLOW and is capped instead of being lifted out. Absolute
   * positioning above the bar was the first attempt and is wrong here: the pill
   * is `overflow: hidden` (so the end buttons' hover follows its rounded edge),
   * which would have clipped the message to nothing — an error state that
   * silently fails to appear is worse than a truncated one.
   *
   * Truncation is VISUAL ONLY. The text node is complete, so the `role="status"`
   * region still announces the whole message; a sighted user sees as much of it
   * as the bar can hold. It is `hidden` at rest, so none of this costs anything
   * in the normal case.
   */
  .tr-share-dock__pill > .tr-vote > .tr-vote__message {
    flex-basis: auto;
    min-inline-size: 0;
    max-inline-size: 12ch;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* ==========================================================================
     THE FALLBACK SHEET
     ==========================================================================
     A popover above the pill, NOT a modal. The theme has a full modal system in
     assets/css/unified/modal.css and this deliberately does not use it: a modal
     traps focus, locks body scroll and paints a full-viewport scrim, all of
     which is the wrong weight for a six-item menu that a tap outside dismisses.

     ORDER IN THE FLOW puts the sheet after the pill in the DOM, and
     `flex-direction: column-reverse` on the root would have been one way to get
     it above; a plain `order` is used instead so that the DOM order — trigger,
     then the thing it controls — stays the order a screen reader and the Tab
     key both follow. */

  .tr-share-dock__sheet {
    order: -1;

    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-1);

    inline-size: min(320px, calc(100vw - var(--space-8)));
    padding: var(--space-2);

    background: var(--surface-base);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-2xl);
    box-shadow: var(--shadow-xl);

    pointer-events: auto;
  }

  /*
   * `[hidden]` is the closed state and it must WIN over the `display: grid`
   * above — a bare `[hidden]` from the UA stylesheet loses to any class
   * selector, which is the single most common way a `hidden` panel ends up
   * visible. Declared explicitly rather than relied on.
   */
  .tr-share-dock__sheet[hidden] {
    display: none;
  }

  .tr-share-dock__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);

    min-block-size: 64px;
    padding: var(--space-2);

    margin: 0;
    border: 0;
    border-radius: var(--radius-lg);
    background: transparent;
    color: var(--color-text-secondary);

    font-family: inherit;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: 1.2;
    text-align: center;
    text-decoration: none;

    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
  }

  .tr-share-dock__item:hover,
  .tr-share-dock__item:focus-visible {
    background: var(--surface-selected);
    color: var(--color-text-primary);
    text-decoration: none;
  }

  .tr-share-dock__item-icon {
    display: inline-flex;
    flex: none;
  }

  .tr-share-dock__item-label {
    /* The bare product name, clipped rather than wrapped: "LinkedIn" in a 96px
       column is the widest of the six, and a two-line label would make one tile
       taller than its neighbours and break the grid's rhythm. */
    max-inline-size: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ==========================================================================
     THE COPIED STATE
     ==========================================================================
     LAST IN THE FILE, and that is load-bearing rather than tidiness. These
     rules hide one of two icons with `display: none`, and both
     `.tr-share-dock__icon` and `.tr-share-dock__item-icon` set `display` at the
     SAME specificity (one class). Declared earlier, `--done { display: none }`
     lost to `__item-icon { display: inline-flex }` further down the file and the
     sheet's Copy tile painted the link mark and the check mark stacked — caught
     at 390px in browser QA, not by reading the file.

     Both icons ship in the markup and this swaps which one paints. The runtime
     writes no text and no style, so the control's width was final at first
     paint — the same decision `.tr-share-row` records, where rewriting a label
     in place measured a 12.6px jump on press. In a fixed pill that jump would
     move the button under the reader's thumb mid-tap. */

  /* `is-copied` is on the CONTROL itself, never on an ancestor, so both
     selectors below are `.control.is-copied .icon` — a descendant combinator
     rooted on the button. Two classes beats the one-class `display` on
     `__icon` / `__item-icon`, so the swap holds in the pill and in the sheet
     without either needing its own copy of the rule. */

  .tr-share-dock__icon--done {
    display: none;
  }

  .tr-share-dock__btn.is-copied .tr-share-dock__icon--rest,
  .tr-share-dock__item.is-copied .tr-share-dock__icon--rest {
    display: none;
  }

  .tr-share-dock__btn.is-copied .tr-share-dock__icon--done,
  .tr-share-dock__item.is-copied .tr-share-dock__icon--done {
    display: inline-flex;
  }

  .tr-share-dock__btn.is-copied,
  .tr-share-dock__item.is-copied {
    color: var(--color-primary);
  }

  /* ==========================================================================
     ROOM AT THE END OF THE PAGE
     ==========================================================================
     The dock floats, so it costs no layout — which is exactly what would let it
     cover the last line of the last section once the reader reaches the bottom.
     One rule, on the class `tiorai_share_dock_body_class()` adds, inside the
     same query as the dock itself.

     On the FOOTER rather than on the content column: the footer is the last
     thing on every single view, it is the same element on all twelve of them,
     and padding there pushes nothing around above it. */

  .tiorai-has-share-dock .site-footer {
    padding-block-end: calc(var(--space-16) + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================================
   REDUCED MOTION
   ============================================================================
   Outside the width query, because a preference is not a viewport. The two
   colour transitions above are the only motion in the file and both are
   removed — there is no transform, no slide and no fade to disable. */

@media (prefers-reduced-motion: reduce) {
  .tr-share-dock,
  .tr-share-dock__btn,
  .tr-share-dock__item {
    transition: none;
  }
}

/* ============================================================================
   FORCED COLORS
   ============================================================================
   Windows High Contrast discards author colours, which would leave the pill and
   the sheet as unbounded floating text over the article. `CanvasText` restores
   the two boundaries that say where each object starts and stops. */

@media (forced-colors: active) {
  .tr-share-dock__pill,
  .tr-share-dock__sheet {
    border-color: CanvasText;
  }

  /*
   * The voted ring comes back. Forced-colors discards the translucent tint that
   * carries the state everywhere else, so without this the only remaining signal
   * would be `aria-pressed` — correct for a screen reader, invisible to a
   * sighted high-contrast user.
   */
  .tr-share-dock__pill > .tr-vote .tr-vote__btn--voted {
    box-shadow: inset 0 0 0 2px Highlight;
  }
}

/* ============================================================================
   PRINT
   ============================================================================
   A floating share control is furniture, not document. It prints as a grey pill
   over the last line of whatever page it lands on. */

@media print {
  .tr-share-dock {
    display: none !important;
  }
}
