/* ==========================================================================
   PROPOSAL — a trial tile set, shown only in the Proposal section of the
   asset sheet. It shares no selector with the game and changes nothing that
   already exists.

   The point of it is not more tiles. It is that every tile obeys the same
   three rules, which is what the current set does not:

   1. ONE SUN. Light comes from the top-left. Everything raised carries the
      same lit top face, the same shaded underside, and the same cast
      shadow — `0 var(--p-rise) 0` in its own colour, plus one soft drop.
      A boulder, a crate and a gem therefore sit at the same height in the
      same light.

   2. ONE GRAIN. Every surface texture repeats at `--p-grain`. Terrains
      differ by angle, colour and shape, never by scale, so no ground looks
      finer or coarser than its neighbour.

   3. ONE RAMP. Every material is three stops — lit, mid, deep — at even
      lightness steps, plus a `cast`. Nothing gets a bespoke gradient.

   From those three, everything below is a recolour plus at most one
   distinguishing detail. Two archetypes carry the whole set, plus a mark
   that can be laid over either:

      .ptile__solid   something standing on the ground   (+1)
      .ptile__well    something cut into the ground      (−1)
      .ptile__glyph   a mark laid over either of them
   ========================================================================== */

/* --- The tile ------------------------------------------------------------ */

/* Sized explicitly. In the game a tile is a grid item and the playfield
   sizes it; here it is a plain child whose contents are all absolutely
   positioned, so without a height it collapses to nothing. */
.ptile {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: var(--f);
  background-image: var(--tex, none);
  box-shadow: inset -1px -1px 0 var(--p-edge);
}

/* --- Archetype 1: standing on the ground --------------------------------- */

.ptile__solid {
  position: absolute;
  inset: 7%;
  border-radius: var(--p-round);
  background: linear-gradient(168deg, var(--s-lit) 0%, var(--s) 52%, var(--s-deep) 100%);
  box-shadow:
    inset 0 2px 0 var(--p-lit),
    inset 0 -3px 0 var(--p-shade),
    inset 0 0 0 1px rgba(0, 0, 0, .22),
    0 var(--p-rise) 0 var(--s-cast),
    0 calc(var(--p-rise) + 3px) 6px var(--p-drop);
}

/* The one highlight every solid shares. A soft wash from the same direction
   as the sun, not a hard clipped facet — a hard edge is what reads as wet
   plastic. Its strength is --p-gloss, and no material sets its own. */
.ptile__solid::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(168deg,
    rgba(255, 255, 255, var(--p-gloss)) 0%,
    transparent 58%);
}

/* --- Archetype 2: cut into the ground ------------------------------------ */

.ptile__well {
  position: absolute;
  inset: 7%;
  border-radius: var(--p-round);
  background: radial-gradient(circle at 50% 62%, var(--w-deep) 0 22%, var(--w) 60%, var(--w-lit) 92%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .16),
    inset 0 -3px 6px rgba(0, 0, 0, .4),
    inset 0 3px 5px rgba(0, 0, 0, .3),
    0 -1px 0 rgba(255, 255, 255, .2);
}

/* A mark laid over a tile: chevrons, bars, teeth. Each tile that uses one
   supplies its own `background-image`. */
.ptile__glyph {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: 50% 50%;
}

/* ==========================================================================
   GROUND — ten surfaces. Every `--tex` repeats at `--p-grain`.
   ========================================================================== */

.ptile--grass {
  --f: var(--m-grass); --p-edge: rgba(30, 62, 24, .34);
  --tex:
    repeating-linear-gradient(78deg, rgba(255, 255, 255, .13) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(-78deg, rgba(24, 58, 20, .16) 0 1px, transparent 1px var(--p-grain));
}

.ptile--moss {
  --f: var(--m-moss); --p-edge: rgba(24, 46, 20, .4);
  --tex:
    repeating-radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .12) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(12deg, rgba(20, 40, 16, .16) 0 1px, transparent 1px var(--p-grain));
}

.ptile--sand {
  --f: var(--m-sand); --p-edge: rgba(150, 116, 58, .34);
  --tex:
    repeating-linear-gradient(96deg, rgba(255, 255, 255, .2) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(84deg, rgba(150, 116, 58, .18) 0 1px, transparent 1px var(--p-grain));
}

.ptile--dirt {
  --f: var(--m-dirt); --p-edge: rgba(70, 46, 24, .42);
  --tex:
    repeating-radial-gradient(circle at 40% 60%, rgba(60, 40, 20, .2) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(88deg, rgba(255, 240, 220, .12) 0 1px, transparent 1px var(--p-grain));
}

.ptile--grit {
  --f: var(--m-grit); --p-edge: rgba(70, 66, 60, .4);
  --tex:
    repeating-radial-gradient(circle at 25% 35%, rgba(255, 255, 255, .16) 0 1px, transparent 1px var(--p-grain)),
    repeating-radial-gradient(circle at 70% 75%, rgba(50, 46, 40, .28) 0 1px, transparent 1px var(--p-grain));
}

/* Flagstones: the grain becomes the joint between cut slabs. */
.ptile--flag {
  --f: var(--m-flag); --p-edge: rgba(70, 66, 60, .45);
  --tex:
    linear-gradient(90deg, rgba(50, 46, 40, .3) 0 2px, transparent 2px),
    linear-gradient(180deg, rgba(50, 46, 40, .3) 0 2px, transparent 2px),
    linear-gradient(180deg, rgba(255, 255, 255, .14) 0 3px, transparent 3px);
  background-size: 50% 50%, 50% 50%, 50% 50%;
}

.ptile--crete {
  --f: var(--m-crete); --p-edge: rgba(90, 88, 82, .42);
  --tex:
    repeating-radial-gradient(circle at 30% 40%, rgba(90, 88, 82, .2) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(92deg, rgba(255, 255, 255, .12) 0 1px, transparent 1px calc(var(--p-grain) + 2px));
}

/* Deck plate: raised treads, one grain apart. */
.ptile--deck {
  --f: var(--m-deck); --p-edge: rgba(50, 58, 64, .5);
  --tex:
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .16) 0 1px, transparent 1px var(--p-grain)),
    repeating-linear-gradient(-45deg, rgba(30, 38, 44, .26) 0 1px, transparent 1px var(--p-grain));
}

.ptile--ice {
  --f: var(--m-ice); --p-edge: rgba(108, 152, 176, .4);
  --tex:
    linear-gradient(122deg, transparent 0 40%, rgba(255, 255, 255, .3) 40% 45%, transparent 45%),
    linear-gradient(28deg, transparent 0 64%, rgba(120, 168, 196, .4) 64% 67%, transparent 67%),
    repeating-linear-gradient(100deg, rgba(255, 255, 255, .14) 0 1px, transparent 1px var(--p-grain));
}

/* Ash, with embers still in it. */
.ptile--ash {
  --f: var(--m-ash); --p-edge: rgba(20, 18, 18, .5);
  --tex:
    repeating-radial-gradient(circle at 35% 45%, rgba(240, 99, 31, .3) 0 1px, transparent 1px calc(var(--p-grain) * 2)),
    repeating-radial-gradient(circle at 65% 20%, rgba(255, 255, 255, .14) 0 1px, transparent 1px var(--p-grain));
}

/* ==========================================================================
   SOLIDS — eight things that stand on the ground. Each is the shared recipe
   plus, at most, one detail.
   ========================================================================== */

.ptile--stone  { --s-lit: var(--m-stone-lit); --s: var(--m-stone); --s-deep: var(--m-stone-deep); --s-cast: var(--m-stone-cast); }
.ptile--brick  { --s-lit: var(--m-brick-lit); --s: var(--m-brick); --s-deep: var(--m-brick-deep); --s-cast: var(--m-brick-cast); }
.ptile--steel  { --s-lit: var(--m-steel-lit); --s: var(--m-steel); --s-deep: var(--m-steel-deep); --s-cast: var(--m-steel-cast); }
.ptile--crate  { --s-lit: var(--m-crate-lit); --s: var(--m-crate); --s-deep: var(--m-crate-deep); --s-cast: var(--m-crate-cast); }
.ptile--hedge  { --s-lit: var(--m-hedge-lit); --s: var(--m-hedge); --s-deep: var(--m-hedge-deep); --s-cast: var(--m-hedge-cast); }
.ptile--pipe   { --s-lit: var(--m-steel-lit); --s: var(--m-steel); --s-deep: var(--m-steel-deep); --s-cast: var(--m-steel-cast); }
.ptile--glass  { --s-lit: var(--m-glass-lit); --s: var(--m-glass); --s-deep: var(--m-glass-deep); --s-cast: var(--m-glass-cast); }
.ptile--rack   { --s-lit: var(--m-rack-lit);  --s: var(--m-rack);  --s-deep: var(--m-rack-deep);  --s-cast: var(--m-rack-cast); }

/* Stone: one weathered pock. */
.ptile--stone .ptile__solid { --p-round: 5px; }

/* Ice brick: a second facet, because it is glass. */
.ptile--brick .ptile__solid::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(311deg, rgba(255, 255, 255, var(--p-gloss2)) 0 18%, transparent 18%);
}

/* Steel cube: four rivets. */
.ptile--steel .ptile__solid::after,
.ptile--rack .ptile__solid::after {
  content: "";
  position: absolute;
  inset: 15%;
  background-image:
    radial-gradient(circle, rgba(255, 255, 255, .32) 0 24%, rgba(30, 40, 48, .48) 30%, transparent 34%),
    radial-gradient(circle, rgba(255, 255, 255, .32) 0 24%, rgba(30, 40, 48, .48) 30%, transparent 34%),
    radial-gradient(circle, rgba(255, 255, 255, .32) 0 24%, rgba(30, 40, 48, .48) 30%, transparent 34%),
    radial-gradient(circle, rgba(255, 255, 255, .32) 0 24%, rgba(30, 40, 48, .48) 30%, transparent 34%);
  background-size: 26% 26%;
  background-position: 0 0, 100% 0, 0 100%, 100% 100%;
  background-repeat: no-repeat;
}

/* Rack: louvred front instead of rivets. */
.ptile--rack .ptile__solid::after {
  inset: 22% 18%;
  background-image: repeating-linear-gradient(180deg,
    rgba(180, 220, 255, .3) 0 1px, transparent 1px 4px);
  background-size: auto;
  background-position: 0 0;
}

/* Crate: banded, corner to corner. */
.ptile--crate .ptile__solid::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image:
    linear-gradient(180deg, transparent 0 42%, rgba(70, 44, 20, .5) 42% 58%, transparent 58%),
    linear-gradient(90deg, transparent 0 42%, rgba(70, 44, 20, .35) 42% 58%, transparent 58%);
}

/* Hedge: a canopy of leaves rather than a face. */
.ptile--hedge .ptile__solid {
  --p-round: 40%;
  background:
    radial-gradient(circle closest-side, var(--m-hedge-lit) 0 60%, transparent 64%) 24% 26% / 46% 46% no-repeat,
    radial-gradient(circle closest-side, var(--m-hedge-lit) 0 60%, transparent 64%) 76% 34% / 42% 42% no-repeat,
    radial-gradient(circle closest-side, var(--m-hedge) 0 60%, transparent 64%) 44% 70% / 50% 50% no-repeat,
    linear-gradient(168deg, var(--s) 0%, var(--s-deep) 100%);
}

/* Pipe: a cylinder, so the light runs down it as a band. */
.ptile--pipe .ptile__solid {
  --p-round: 40% / 14%;
  background: linear-gradient(90deg,
    var(--m-steel-deep) 0%, var(--m-steel) 22%,
    var(--m-steel-lit) 40%, var(--m-steel) 62%, var(--m-steel-deep) 100%);
}

.ptile--pipe .ptile__solid::before { display: none; }

/* Obsidian: faceted, so the highlight breaks. */
.ptile--glass .ptile__solid::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(214deg, rgba(255, 255, 255, var(--p-gloss2)) 0 20%, transparent 20%),
    linear-gradient(38deg, rgba(180, 140, 220, calc(var(--p-gloss2) * 1.6)) 0 28%, transparent 28%);
}

/* ==========================================================================
   SUNKEN — six things cut into the ground.
   ========================================================================== */

/* Four walls meeting in the middle, lit as a hole and not as a bump: with
   the sun at the top-left, the inner faces of the top and left walls fall
   into shadow and the bottom and right walls catch the light. That is the
   exact reverse of every solid in this file, which is what makes one read as
   going in and the other as coming out. */
.ptile--pit .ptile__well {
  inset: 0;
  border-radius: 0;
  background: conic-gradient(from 45deg,
    color-mix(in srgb, var(--m-dirt-lit) 55%, var(--m-dirt-deep)) 0deg 90deg,
    var(--m-dirt-lit) 90deg 180deg,
    var(--m-dirt-deep) 180deg 270deg,
    color-mix(in srgb, var(--m-dirt-deep) 60%, black) 270deg 360deg);
  /* Barely any shadow. The four wall values ARE the shading here, and on a
     56px tile the wall band is only about 18px wide — a 6px inner glow and a
     7px spread off the floor square between them left almost none of it
     showing, which is why the walls did not read at all. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .3);
}

.ptile--pit .ptile__well::after {
  content: "";
  position: absolute;
  inset: 17%;
  border-radius: 1px;
  background: var(--m-void-deep);
  box-shadow: 0 0 2px rgba(0, 0, 0, .5);
}

.ptile--void {
  --w-lit: var(--m-void-lit); --w: var(--m-void); --w-deep: var(--m-void-null);
}

/* Void: the grid itself has failed. */
.ptile--void .ptile__well::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image:
    repeating-linear-gradient(90deg, rgba(120, 90, 200, .34) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(180deg, rgba(120, 90, 200, .34) 0 1px, transparent 1px 7px);
  animation: p-flicker 2.6s steps(3, end) infinite;
}

@keyframes p-flicker {
  0%, 100% { opacity: .8; }
  50%      { opacity: .35; }
}

/* Lava sits level with the ground, not below it: it is a pool, not a pit. */
.ptile--lava .ptile__well {
  inset: 0;
  border-radius: 0;
  background:
    radial-gradient(circle closest-side, rgba(255, 244, 200, .95) 0 34%, transparent 40%) 30% 32% / 34% 34% no-repeat,
    radial-gradient(circle closest-side, rgba(255, 226, 160, .8) 0 34%, transparent 40%) 70% 66% / 26% 26% no-repeat,
    linear-gradient(158deg, var(--m-lava-lit) 0%, var(--m-lava) 52%, var(--m-lava-deep) 100%);
  box-shadow:
    inset 0 0 0 2px var(--m-lava-cast),
    inset 0 0 12px rgba(255, 140, 40, .65);
  animation: p-molten 3.8s ease-in-out infinite;
}

@keyframes p-molten {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.18); }
}

.ptile--water .ptile__well {
  inset: 0;
  border-radius: 0;
  background:
    repeating-linear-gradient(96deg, rgba(255, 255, 255, .28) 0 1px, transparent 1px calc(var(--p-grain) + 3px)),
    linear-gradient(180deg, var(--m-water-lit) 0%, var(--m-water) 42%, var(--m-water-deep) 100%);
  box-shadow:
    inset 0 0 0 2px var(--m-water-cast),
    inset 0 4px 10px rgba(0, 30, 50, .5);
  animation: p-swell 4.6s ease-in-out infinite;
}

@keyframes p-swell {
  0%, 100% { background-position: 0 0, 0 0; }
  50%      { background-position: 7px 0, 0 0; }
}

/* Spikes: steel teeth in a socket, so both archetypes at once. */
.ptile--spikes {
  --w-lit: var(--m-steel-deep); --w: var(--m-steel-cast); --w-deep: var(--m-void);
}

.ptile--spikes .ptile__well::after {
  content: "";
  position: absolute;
  inset: 14%;
  background-image:
    conic-gradient(from 180deg at 50% 100%, transparent 0 42%, var(--m-steel-lit) 42% 50%, var(--m-steel-deep) 50% 58%, transparent 58%),
    conic-gradient(from 180deg at 50% 100%, transparent 0 42%, var(--m-steel-lit) 42% 50%, var(--m-steel-deep) 50% 58%, transparent 58%),
    conic-gradient(from 180deg at 50% 100%, transparent 0 42%, var(--m-steel-lit) 42% 50%, var(--m-steel-deep) 50% 58%, transparent 58%);
  background-size: 30% 60%;
  background-position: 4% 100%, 50% 100%, 96% 100%;
  background-repeat: no-repeat;
  filter: drop-shadow(0 -1px 1px rgba(0, 0, 0, .5));
}

/* Vent: a grille with steam standing over it. */
.ptile--vent {
  --w-lit: var(--m-deck-lit); --w: var(--m-deck-deep); --w-deep: var(--m-void);
}

.ptile--vent .ptile__well::after {
  content: "";
  position: absolute;
  inset: 16%;
  border-radius: 2px;
  background-image: repeating-linear-gradient(180deg,
    var(--m-deck-lit) 0 2px, rgba(10, 14, 18, .85) 2px 5px);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .5);
}

.ptile--vent .ptile__glyph {
  background-image:
    radial-gradient(circle closest-side, rgba(255, 255, 255, .55) 0 60%, transparent 64%),
    radial-gradient(circle closest-side, rgba(255, 255, 255, .4) 0 60%, transparent 64%);
  background-size: 34% 34%, 24% 24%;
  background-position: 42% 34%, 62% 20%;
  animation: p-steam 3.4s ease-in-out infinite;
}

@keyframes p-steam {
  0%, 100% { opacity: .25; transform: translateY(6%) scale(.9); }
  50%      { opacity: .8;  transform: translateY(-8%) scale(1.08); }
}

.ptile--pad {
  --f: var(--m-crete-deep); --p-edge: rgba(60, 50, 80, .5);
  --tex: repeating-linear-gradient(45deg, rgba(171, 99, 240, .18) 0 1px, transparent 1px var(--p-grain));
}

/* Sized and cropped exactly like the gates. It is the same object — a disc
   of light in the floor — so it obeys the same geometry. */
.ptile--pad .ptile__well {
  inset: -24%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 44%,
    var(--m-warp-lit) 0 10%, var(--m-warp) 26%, var(--m-warp-deep) 52%, var(--m-warp-cast) 78%);
  box-shadow: none;
  animation: p-breathe 3.2s ease-in-out infinite;
}

/* Rings rather than a vortex: the pad does not lead anywhere, it repeats. */
.ptile--pad .ptile__well::after {
  content: "";
  position: absolute;
  inset: 26%;
  border-radius: 50%;
  background: repeating-radial-gradient(circle at 50% 50%,
    transparent 0 12%,
    rgba(240, 220, 255, .5) 12% 18%,
    transparent 18% 30%);
  animation: p-pulse 2.4s ease-in-out infinite;
}

@keyframes p-pulse {
  0%, 100% { transform: scale(.86); opacity: .35; }
  50%      { transform: scale(1); opacity: .9; }
}

/* ==========================================================================
   MARKERS — where a run begins and where it ends.
   ========================================================================== */

.ptile--start {
  --f: var(--m-crete-deep); --p-edge: rgba(70, 66, 60, .5);
  --tex:
    repeating-linear-gradient(45deg, var(--m-key) 0 4px, rgba(40, 34, 22, .8) 4px 8px);
}

.ptile--start .ptile__well {
  inset: 16%;
  --w-lit: var(--m-crete-lit); --w: var(--m-crete); --w-deep: var(--m-crete-deep);
}

.ptile--portal   { --g: var(--m-warp); --g-lit: var(--m-warp-lit); --g-deep: var(--m-warp-deep); --g-cast: var(--m-warp-cast); }
.ptile--check    { --g: var(--m-safe); --g-lit: var(--m-safe-lit); --g-deep: var(--m-safe-deep); --g-cast: var(--m-safe-cast); }
.ptile--locked   { --g: var(--m-warp); --g-lit: var(--m-warp-lit); --g-deep: var(--m-warp-deep); --g-cast: var(--m-warp-cast); }

@keyframes p-turn {
  to { transform: rotate(1turn); }
}

/* A gate of light: a disc big enough to fill its tile, cropped by it.

   To cover a square, a disc has to clear the DIAGONAL, not the edges — a
   radius of at least half the diagonal, which is 70.7% of the tile. At -24%
   the disc is 148% across, so its radius is 74% and it covers the corners
   with a little to spare. Anything under 70.7% and the corners show through.

   Once it fills the tile, every edge treatment the disc carried is outside
   the square and clipped away, so the square's own edge and its inner shade
   move onto the tile below. What is left of the disc is the light: bright at
   the middle, falling to its darkest in the corners.

   It is set INTO the floor rather than standing on it, so unlike every other
   solid it takes no cast shadow. It is a hole with light coming out. */
.ptile--portal,
.ptile--check,
.ptile--locked,
.ptile--pad {
  overflow: hidden;
  box-shadow:
    inset -1px -1px 0 var(--p-edge),
    inset 0 0 0 1px rgba(0, 0, 0, .4),
    inset 0 0 12px rgba(0, 0, 0, .5);
}

.ptile--portal .ptile__solid,
.ptile--check .ptile__solid,
.ptile--locked .ptile__solid {
  --p-round: 50%;
  inset: -24%;
  background: radial-gradient(circle at 50% 44%,
    var(--g-lit) 0 10%, var(--g) 26%, var(--g-deep) 52%, var(--g-cast) 78%);
  animation: p-breathe 3.2s ease-in-out infinite;
}

.ptile--portal .ptile__solid::before,
.ptile--check .ptile__solid::before,
.ptile--locked .ptile__solid::before {
  inset: 26%;
  border-radius: 50%;
  background: conic-gradient(from 0turn,
    transparent 0 8%, var(--g-lit) 18%, transparent 34%,
    var(--g) 52%, transparent 68%, var(--g-lit) 84%, transparent 96%);
  opacity: .85;
  animation: p-turn 4.6s linear infinite;
}

/* The glow used to sit outside the disc, which is now outside the tile and
   clipped away. So the light pulses rather than the halo. */
@keyframes p-breathe {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.2); }
}

/* Locked: a bar across the mouth, waiting on a key. */
.ptile--locked .ptile__glyph {
  background-image:
    linear-gradient(180deg, var(--m-steel-lit) 0 22%, var(--m-steel-deep) 22% 100%);
  background-size: 74% 16%;
  background-position: 50% 50%;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .6));
}

/* --- Sheet layout for the section ---------------------------------------- */

.proposal {
  --p-round: 3px;
  display: grid;
  gap: clamp(var(--gap-5), 4vw, var(--gap-6));
  margin-top: var(--gap-4);
}

.pgroup { display: grid; gap: var(--gap-3); }

.pgroup__name {
  font-family: var(--font-pixel);
  font-size: .72rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--sheet-soft);
}

.pgroup__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-4);
}

.pspec { display: grid; justify-items: center; gap: var(--gap-2); }

.pspec__cell {
  position: relative;
  width: var(--tile-size);
  height: var(--tile-size);
}

.pspec__name {
  font-family: var(--font-pixel);
  font-size: .68rem;
  color: var(--sheet-ink);
}
