/* InstantPalette - gradient generator (/gradient-generator) only.
   Layer 5: loaded after tokens.css, base.css, site.css and tools.css, and nothing else loads it.

   Only what is genuinely specific to this tool lives here: the preview stage and its checkerboard, the mesh
   pins, the stop bar and its handles, the angle dial, the text-contrast block and the preset grid.
   Buttons, inputs, sliders, segmented controls, code blocks, the FAQ and the page shell all come from the
   shared layers - if something here looks like a restyled shared component, it is a bug. */

/* ================= Preview ================= */
/* The stage carries the checkerboard so stop opacity is visible; the preview itself paints only the gradient
   (plus the grain layer), which keeps it byte-for-byte what the export produces. */
.gstage {
  margin: 0 0 20px;
  border-radius: var(--r-lg);
  background:
    repeating-conic-gradient(var(--sunken) 0% 25%, var(--raised) 0% 50%) 0 0 / 18px 18px;
  box-shadow: inset 0 0 0 1px var(--line-2);
}
.gpreview {
  position: relative;
  width: 100%;
  height: clamp(180px, min(40vw, 44vh), 380px);
  border-radius: var(--r-lg);
  background-color: transparent;
  background-repeat: repeat, no-repeat;
  /* No touch-action here: the preview itself is not draggable, and in linear/radial/conic mode it is the
     biggest thing on a phone screen - blocking touch-action would stop the page scrolling. The mesh pins
     carry their own touch-action: none, which is what captures a drag. */
}

/* Mesh points. The ring is drawn in the point's own adaptive ink over its anti colour, so it stays visible on
   any gradient; focus thickens the same ring rather than swapping to a hue. */
.gpins { position: absolute; inset: 0; }
.gpin {
  --ink: #000; --anti: #FFF;
  position: absolute;
  left: var(--x, 50%); top: var(--y, 50%);
  width: 34px; height: 34px; margin: 0; padding: 0;
  transform: translate(-50%, -50%);
  border: 0; border-radius: 50%;
  background: var(--c, #888);
  box-shadow: 0 0 0 2px var(--anti), 0 0 0 4px var(--ink);
  cursor: grab;
  touch-action: none;
}
.gpin::after {
  content: ""; position: absolute; inset: -6px; border-radius: 50%;   /* 46px touch target */
}
.gpin[data-sel="1"] { z-index: 2; box-shadow: 0 0 0 3px var(--anti), 0 0 0 6px var(--ink); }
.gpin:focus-visible { z-index: 3; outline: 2px solid var(--ink); outline-offset: 4px; box-shadow: 0 0 0 3px var(--anti), 0 0 0 6px var(--ink); }
.gpin:active { cursor: grabbing; }

/* ================= Stop bar ================= */
.gstops .tpanel-hd { flex-wrap: wrap; }
.gacts { display: flex; flex-wrap: wrap; gap: 8px; }

/* Refused, not removed: the button keeps its place in the tab order and answers with a toast */
.gstops .btn-o[aria-disabled="true"], .gedit .btn-o[aria-disabled="true"] {
  color: var(--ink-3); border-style: dashed; cursor: default;
}
.gstops .btn-o[aria-disabled="true"] .i, .gedit .btn-o[aria-disabled="true"] .i { color: var(--ink-3); }

.gbar-wrap { display: flex; flex-direction: column; gap: 10px; }
.gbar {
  position: relative;
  height: 52px;
  margin: 6px 13px 0;
  border-radius: var(--r-sm);
}
.gbar-track {
  position: absolute; inset: 0;
  border-radius: var(--r-sm);
  background:
    repeating-conic-gradient(var(--sunken) 0% 25%, var(--raised) 0% 50%) 0 0 / 14px 14px;
  box-shadow: inset 0 0 0 1px var(--line-2);
  overflow: hidden;
}
.gbar-track::after {
  content: ""; position: absolute; inset: 0;
  background-image: var(--ramp, none);
}
.gbar-hits { position: absolute; inset: 0; }
/* A stop handle: a 22px dot inside a 30x60 box, widened to 44x60 by the ::after hit area below, so a
   fingertip clears 44px in both axes without the dots visually colliding at the 8-stop maximum */
.gstop {
  position: absolute;
  left: var(--x, 0%); top: 50%;
  width: 30px; height: 60px; padding: 0;
  transform: translate(-50%, -50%);
  border: 0; background: none;
  display: grid; place-items: center;
  cursor: grab;
  touch-action: none;
}
.gstop::before {
  content: "";
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--c, #888);
  box-shadow: 0 0 0 2px var(--raised), 0 0 0 3.5px var(--ink-1);
}
/* Hit area only, like .gpin::after: 30px + 7px each side = 44px, no paint of its own */
.gstop::after {
  content: ""; position: absolute; inset: 0 -7px;
}
.gstop[data-sel="1"]::before { width: 28px; height: 28px; box-shadow: 0 0 0 3px var(--raised), 0 0 0 5px var(--ink-1); }
/* Stops can sit on top of each other, so the one being used is raised above the pile: the selected handle
   paints over its neighbours, and the focused one over everything, or its focus ring would be half hidden. */
.gstop[data-sel="1"] { z-index: 2; }
.gstop:focus-visible { outline: none; z-index: 3; }
/* The button box is a 30x60 rectangle, so the ring goes on the round ::before instead of on the outline of
   the box. Alternating raised / ink bands read on any gradient underneath, and at 4 bands against the
   selected state's 2 the difference is unmistakable - a 1px thicker ring was not. */
.gstop:focus-visible::before {
  width: 28px; height: 28px;
  box-shadow:
    0 0 0 3px var(--raised), 0 0 0 5px var(--ink-1),
    0 0 0 7px var(--raised), 0 0 0 9px var(--ink-1);
}
.gstop:active { cursor: grabbing; }

/* The selected stop / point editor */
.gedit { align-items: flex-end; }
.gedit .thex { width: 100%; }
.gedit .field:first-child { flex: 1 1 200px; min-width: 176px; }
.gedit .tslider { min-width: 132px; }
/* The system colour well is a real <input type="color">: strip the platform chrome, keep the 44px box */
input.twell {
  -webkit-appearance: none; appearance: none;
  border: 1px solid var(--line-2);
  cursor: pointer;
}
input.twell::-webkit-color-swatch-wrapper { padding: 3px; }
input.twell::-webkit-color-swatch { border: 0; border-radius: 5px; }
input.twell::-moz-color-swatch { border: 0; border-radius: 5px; }

/* ================= Angle dial ================= */
.gdial-row { display: flex; align-items: flex-end; gap: 12px; }
.gdial {
  position: relative;
  width: 76px; height: 76px; flex: none;
  border-radius: 50%;
  background: var(--sunken);
  box-shadow: inset 0 0 0 1px var(--line-2);
  cursor: grab;
  touch-action: none;
}
.gdial-hand {
  position: absolute; left: 50%; top: 50%;
  width: 2px; height: 30px;
  transform-origin: 50% 100%;
  /* 0deg in CSS gradients points up; the hand is drawn upwards and rotated by the same angle */
  transform: translate(-50%, -100%) rotate(var(--a, 180deg));
  background: var(--ink-1); border-radius: 1px;
}
.gdial-dot {
  position: absolute; left: 50%; top: 50%;
  width: 8px; height: 8px;
  transform: translate(-50%, -50%);
  border-radius: 50%; background: var(--ink-1);
}
.gdial:focus-visible { outline: 2px solid var(--ink-1); outline-offset: 3px; }
.gdial:active { cursor: grabbing; }
.gnum { width: 96px; flex: none; }
.gdial-f { flex: none; }
/* the grain slider shares the geometry row: give it a sane width instead of all the space that is left */
#row-geo .tslider { flex: 0 1 300px; min-width: 180px; }

/* ================= Text contrast ================= */
.gcon { display: grid; gap: 10px; grid-template-columns: 1fr; margin: 0 0 10px; }
.gcon-spec {
  display: flex; align-items: center;
  min-height: 72px; padding: 12px 16px;
  border-radius: var(--r);
  background-image: var(--ramp, none);
  background-color: var(--sunken);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 12%, transparent);
}
.gcon-sample { margin: 0; font: 600 17px/1.35 var(--f-sans); }
.gcon-read {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 12px 24px; margin: 4px 0 0;
}
.gcon-read dt { font: 400 12px/16px var(--f-sans); color: var(--ink-2); }
.gcon-read dd { margin: 2px 0 0; display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.gcon-read .tbig { font-size: 28px; }
.gcon-at { font: 500 12px/1.4 var(--f-mono); color: var(--ink-2); }
@media (min-width: 680px) {
  .gcon { grid-template-columns: 1fr 1fr; }
}

/* ================= Export ================= */
.gexp-row { align-items: flex-end; margin: 0 0 12px; }
.gexp-row:last-child { margin: 12px 0 0; }
.gexp-row .field:first-child { flex: 0 1 auto; }
.codeout pre { white-space: pre-wrap; overflow-wrap: anywhere; }
#code-note { max-width: 36ch; text-align: right; }

/* ================= Presets ================= */
.gpresets {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); gap: 12px;
}
.gpreset {
  display: flex; flex-direction: column; gap: 8px;
  width: 100%; padding: 0;
  border: 0; background: none; color: var(--ink-1);
  text-align: left;
}
.gpreset .sw {
  height: 64px; border-radius: var(--r);
  background-image: var(--ramp, none);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 12%, transparent);
}
.gpreset .nm { font: 500 13px/1.3 var(--f-sans); }
.gpreset:focus-visible .sw { outline: 2px solid var(--ink-1); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .gpreset:hover .sw { box-shadow: inset 0 0 0 2px var(--ink-1); }
}

/* ================= Narrow screens ================= */
@media (max-width: 600px) {
  .gacts { width: 100%; }
  .gacts .btn-o { flex: 1 1 auto; height: 44px; }
  .gbar { height: 56px; }
  .gedit .field:first-child { flex: 1 1 100%; }
  .gcon-read .tbig { font-size: 24px; }
  #code-note { display: none; }
  .gexp-row .tprimary { flex: 1 1 auto; }
}

/* ================= Landscape phones =================
   Only ~390px of height: tighten the head block and shorten the stage so at least the stop bar - a real
   control - is on screen with the preview, the way the other three tools are. */
@media (orientation: landscape) and (max-height: 500px) {
  .tpage { padding-top: 16px; }
  .page-hd { margin-bottom: 16px; }
  .tpage h1 { margin-bottom: 6px; font-size: 24px; }
  .tpage .page-sub { font-size: 15px; }
  .gstage { margin-bottom: 14px; }
  .gpreview { height: clamp(110px, 30vh, 150px); }
}

@media (prefers-reduced-motion: reduce) {
  .gpin, .gstop, .gdial-hand { transition: none !important; }
}
