/*
  QRCodeGenerator — primitives (docs/08-UI-SPEC.md §9.1, §9.4, §9.6).

  The handful of things every page needs and no page should re-invent: the icon
  element, the layout rhythms, the surface, and the two accessibility helpers.
  Components — buttons, fields, tables, the preview — belong to the pages that
  own them and land with tasks 6.1 onwards, in @layer components.
*/

@layer primitives {
    /* ── Icons ─────────────────────────────────────────────────────────────
       One sprite, no icon font, no runtime fetch. An icon inherits the text
       colour and the current font size, so it never needs a size of its own:

         <svg class="icon" aria-hidden="true"><use href="/icons.svg#i-qr-code" /></svg>
    */
    .icon {
        inline-size: 1.25em;
        block-size: 1.25em;
        flex: none;
        color: inherit;
        vertical-align: -0.2em;

        /*
          The stroke settings are HERE and not on the sprite, and that is not a
          style choice — it is what makes the icons draw at all. `<use>` clones
          the referenced <symbol> and its subtree into this document; the
          attributes on the sprite file's own root <svg> are not part of that
          subtree, so they never arrive. Every symbol was therefore being
          painted with the SVG defaults — filled black, no stroke — which turns
          a line icon into a blob and makes Lucide's zero-length "dot" paths
          disappear entirely.

          `fill` and `stroke` are inherited properties, and inheritance does
          cross the shadow boundary a <use> creates, so declaring them on the
          host element reaches the cloned content. The sprite keeps its own copy
          of them for anybody who opens the file directly.
        */
        fill: none;
        stroke: currentColor;
        stroke-width: 2;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    .icon--sm { inline-size: 1em; block-size: 1em; }
    .icon--lg { inline-size: 1.75em; block-size: 1.75em; }

    /* ── Rhythm ────────────────────────────────────────────────────────────
       Two layout primitives cover most of a page: things stacked with one
       gap, and things in a row that wraps. Both take their gap from a token
       so a component never writes a margin.
    */
    .stack {
        display: flex;
        flex-direction: column;
        gap: var(--stack-gap, var(--space-4));
    }

    .cluster {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--cluster-gap, var(--space-3));
    }

    /* Prose that stays readable: capped at the measure, never wider. */
    .measure {
        max-inline-size: var(--measure);
    }

    /* ── Surfaces ──────────────────────────────────────────────────────────
       A panel is a surface, a border and a radius — in dark mode the raised
       one is expressed with lightness rather than a heavier shadow, which is
       why the token changes and the shadow does not.
    */
    .surface {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--r-lg);
        padding: var(--density-space);
    }

    .surface--raised {
        background: var(--surface);
        box-shadow: var(--shadow-md);
    }

    @media (prefers-color-scheme: dark) {
        .surface--raised {
            background: var(--surface-2);
            box-shadow: none;
        }
    }

    /* ── Type helpers ──────────────────────────────────────────────────────
       The eyebrow is the one place §9.3 allows letter-spaced upper case.
    */
    .eyebrow {
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        letter-spacing: var(--tracking-eyebrow);
        text-transform: uppercase;
        color: var(--text-muted);
    }

    .muted { color: var(--text-muted); }

    .mono {
        font-family: var(--font-mono);
        font-variant-numeric: tabular-nums;
    }

    /* Every figure a user compares against another figure. */
    .numeric { font-variant-numeric: tabular-nums; }

    /* ── Accessibility ─────────────────────────────────────────────────────
       Available to a screen reader, invisible to everyone else. `:not(:focus)`
       so a skip link becomes visible when it is tabbed to.
    */
    .visually-hidden:not(:focus):not(:active) {
        position: absolute;
        inline-size: 1px;
        block-size: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    /* For a wrapper that has to draw the ring for a child input. */
    .focus-ring:has(:focus-visible) {
        outline: var(--focus-ring-width) solid var(--focus-ring-color);
        outline-offset: var(--focus-ring-offset);
    }

    /* ── Shell chrome ──────────────────────────────────────────────────────
       Every shell needs exactly one of each of these and none of them may
       differ between the public one and the admin one, so they live here
       rather than in a layout's scoped file — where task 6.1 would have had
       to write them twice and task 6.6b a third time.
    */

    /* The product's name and mark. Identical in both shells, so it is written once. */
    .brand {
        display: inline-flex;
        align-items: center;
        gap: var(--space-2);
        color: var(--text);
        text-decoration: none;
    }

    .brand:hover {
        color: var(--accent);
    }

    .brand__name {
        font-size: var(--text-md);
        font-weight: var(--weight-semibold);
        letter-spacing: var(--tracking-display);
    }

    /* The first thing a keyboard user reaches, and invisible until they do. */
    .skip-link {
        position: absolute;
        inset-block-start: var(--space-2);
        inset-inline-start: var(--space-2);
        z-index: var(--z-toast);
        padding: var(--space-2) var(--space-4);
        border-radius: var(--r-md);
        background: var(--surface);
        color: var(--text);
        box-shadow: var(--shadow-md);
        transform: translateY(-200%);
        transition: transform var(--dur-instant) var(--ease-out);
    }

    .skip-link:focus-visible {
        transform: translateY(0);
    }

    /*
      The framework's own error strip. It is the last thing a user sees when
      the circuit is gone, so it is styled rather than left as the template's
      yellow banner — but it stays a strip, because a modal over a broken page
      is worse.

      Laid out as a block, not a flex row: the framework shows it by setting
      `style="display: block"`, which would overwrite any display of ours.
    */
    #blazor-error-ui {
        display: none;
        position: fixed;
        inset-inline: 0;
        inset-block-end: 0;
        z-index: var(--z-toast);

        padding: var(--space-3) var(--space-4);

        background: var(--surface);
        border-block-start: 1px solid var(--border);
        box-shadow: var(--shadow-lg);
        color: var(--text);
        font-size: var(--text-sm);
    }

    #blazor-error-ui .reload {
        margin-inline-start: var(--space-4);
        cursor: pointer;
    }

    #blazor-error-ui .dismiss {
        float: inline-end;
        cursor: pointer;
        color: var(--text-muted);
        font-size: var(--text-md);
        line-height: 1;
    }
}
