/* styles/surfaces.css
 * Surface Library from the canvas (coGvv EzEdh): page, paper, card, muted, inverse,
 * inverse-textured, borders, radii, elevation, dither edges and grain. Textures live in
 * /assets/textures and are byte-identical to the design repo's tex-*.png, except the grain: a lossless
 * WebP of the design repo's tex-grain-light.png (same 1440px pixels). The board draws grain
 * (1440px square) with image mode cover; it is anchored top-left so it lands on whole pixels.
 * Edges tile along x at a whole-pixel scale, so the dither cells stay square at every width
 * (BRI-7805 J11, which overrides the board's stretch): 3px cells on M and D (the textures at
 * 1:1) and 4px cells on W (the 1920 frames' cover scale). The textures are whole cells wide
 * (390 = 130 x 3, 1440 = 480 x 3) and the dither has no horizontal structure, so the repeats
 * meet without a seam. */
@layer surfaces {
  .surface--page {
    background: var(--white);
    color: var(--ink);
  }

  .surface--paper {
    background: var(--paper);
    color: var(--ink);
  }

  /* Same values as page; border, radius and elevation come from their own classes */
  .surface--card {
    background: var(--white);
    color: var(--ink);
  }

  .surface--muted {
    background: var(--mist);
    color: var(--ink);
  }

  .surface--inverse,
  .surface--inverse-textured {
    --focus-ring: var(--mist);
    --selection-bg: var(--white);
    --selection-fg: var(--fern);

    background: var(--fern);
    color: var(--white);
  }

  .surface--inverse-textured {
    background-image: url("/assets/textures/tex-grain-light.webp");
    background-position: 0 0;
    background-size: cover;
    background-repeat: no-repeat;
  }

  /* Grain overlay for any surface that needs it without changing its fill */
  .grain {
    position: relative;
    isolation: isolate;
  }

  .grain::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: url("/assets/textures/tex-grain-light.webp") 0 0 / cover no-repeat;
    pointer-events: none;
  }

  /* Borders */
  .border--soft { border: 1px solid var(--line); }
  .border--default { border: 1px solid var(--line-2); }
  .border--strong { border: 1px solid var(--rule-edge); }
  .border--cell { border: 1px solid var(--rule-cell); }

  .radius--sm { border-radius: var(--radius-sm); }
  .radius--md { border-radius: var(--radius-md); }
  .radius--lg { border-radius: var(--radius-lg); }
  .radius--xl { border-radius: var(--radius-xl); }
  .radius--pill { border-radius: var(--radius-pill); }

  .elevation--subtle { box-shadow: var(--elevation-subtle); }
  .elevation--low { box-shadow: var(--elevation-low); }
  .elevation--floating { box-shadow: var(--elevation-floating); }
  .elevation--window { box-shadow: var(--elevation-window); }
  .elevation--raised { box-shadow: var(--elevation-raised); }
  .elevation--overlay { box-shadow: var(--elevation-overlay); }

  /* Dither edges sit on the light section that touches a dark one. A hard cut is equally valid.
     The dither is a mask over the band's own surface, fern under the grain as
     .surface--inverse-textured draws it, so the dark cells carry the band's grain and the edge
     and the band read as one textured surface (BRI-7805 J58). The textures hold two colours,
     fern and clear, so as a mask they draw the same cells; the light cells show the section
     untouched. An edge on a flat band (.surface--inverse) drops the grain. */
  .edge-top,
  .edge-bottom {
    --edge-tex-h: 60px;
    --edge-cell: 3px;
    --edge-fill: var(--fern);
    --edge-grain: url("/assets/textures/tex-grain-light.webp");
    position: relative;
  }

  .surface--inverse + .edge-top,
  .edge-bottom:has(+ .surface--inverse) {
    --edge-grain: none;
  }

  /* The dark side of the texture sits on the section's edge; when the box is taller than the
     texture (73 on D against 72), the extra row is on the light side. */
  .edge-top::before,
  .edge-bottom::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    height: var(--edge-h);
    background: var(--edge-grain) 0 0 / cover no-repeat, var(--edge-fill);
    mask-repeat: repeat-x, no-repeat;
    mask-size: auto var(--edge-tex-h), 100% var(--edge-cell);
    image-rendering: pixelated;
    pointer-events: none;
  }

  /* Under the texture, one dither cell (--edge-cell) of solid mask lines the section's edge:
     Chrome can paint an image's edge row light where one tile spans the whole box (1920), and
     this keeps the dither meeting the band with no strip (BRI-7805 J54). */
  .edge-top::before {
    top: 0;
    mask-image: url("/assets/textures/tex-edge-top-m.png"), linear-gradient(var(--fern), var(--fern));
    mask-position: 0 0;
  }

  .edge-bottom::after {
    bottom: 0;
    mask-image: url("/assets/textures/tex-edge-bottom-m.png"), linear-gradient(var(--fern), var(--fern));
    mask-position: 0 100%;
  }

  @media (min-width: 900px) {
    .edge-top,
    .edge-bottom {
      --edge-tex-h: 72px;
    }

    .edge-top::before {
      mask-image: url("/assets/textures/tex-edge-top.png"), linear-gradient(var(--fern), var(--fern));
    }

    .edge-bottom::after {
      mask-image: url("/assets/textures/tex-edge-bottom.png"), linear-gradient(var(--fern), var(--fern));
    }
  }

  /* At 1x on D the grain draws at about 1:1; nearest-neighbour sampling keeps it on whole
     pixels wherever the section lands (a fractional top otherwise blurs it). */
  @media (min-width: 900px) and (max-resolution: 1dppx) {
    .surface--inverse-textured,
    .grain::before {
      image-rendering: pixelated;
    }
  }

  @media (min-width: 1680px) {
    .surface--inverse-textured,
    .grain::before {
      image-rendering: auto;
    }

    /* 4px cells (the 1440 texture at 4/3, 96px tall). The dark side stays on the section's
       edge, as on M and D, so the solid rows meet the band with no light strip (BRI-7805 J54);
       the light side is what the box crops. */
    .edge-top,
    .edge-bottom {
      --edge-tex-h: 96px;
      --edge-cell: 4px;
    }
  }

  @media (forced-colors: active) {
    .edge-top::before,
    .edge-bottom::after,
    .grain::before {
      display: none;
    }
  }
}
