/* ==========================================================================
   KAZ COATINGS — Color Studio (KAZ-746)
   Loaded only on pages that render a studio, by color_studio_head().

   A second stylesheet rather than more of style.css, matching admin.css:
   this is one component on two pages, not site furniture, and the KAZ-746 §3
   manifest names the file. Everything here is namespaced .cs- so it cannot
   reach the rest of the site. Tokens (--orange, --offwhite, --hair, --r ...)
   come from style.css and are not redefined.

   PHASE 1.1 — catalog engine only. No generator preview stage.
   No price rule and no popularity rule lives here, because no such element
   exists in the markup and none may be added — KAZ-746 §2.
   ========================================================================== */

/* ============ SECTION ============ */
/* Sits between Options (.s-char) and the hidden photo strip on the flake page.
   .s-deep is the darkest surface on the site, which is the point: a swatch has
   to be judged against a quiet ground, not against the metallic background
   layer showing through .s-open. */
.cs-sec .sec-head{margin-bottom:40px}
.cs-sec .lede{margin-top:14px}

.cs{display:grid;gap:38px}

/* The option groups as one column. Below the sticky breakpoint this is exactly
   the stack .cs used to be; above it, it becomes the tall left column the
   selection panel sticks alongside. */
.cs-groups{display:grid;gap:38px}

/* ============ GROUPS ============ */
.cs-group{display:grid;gap:14px}
.cs-gt{
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:1.02rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--silver);margin:0;
}
/* ---- The Solid Color swap — KAZ-746 §5.1 ----------------------------------
   Two rules, and between them they are the whole of "the swap must not shift
   layout".

   .cs-swap holds the blend grid and the solids grid in ONE grid cell, stacked.
   A grid row is sized to its tallest item, so the color group is permanently as
   tall as the taller of the two grids whichever one is showing. Swapping
   changes what is painted and nothing about the geometry — not "close enough
   to zero", but zero, and it holds however far the two pools drift apart in
   length. (They are both twelve entries today, so there is no reserved slack at
   any column count; that is tidiness, not a constraint. §12 requires adding a
   solid to be a one-file change, and it stays one.)

   visibility, not display, in both rules: display:none would collapse the box
   and move the page, which is the exact thing §5.1 forbids. visibility keeps
   the box and still takes the subtree out of the tab order and the
   accessibility tree.

   Nothing transitions. There is no shift here to smooth over. */
.cs-swap{display:grid}
.cs-swap > *{grid-area:1/1}
.cs-swap > [data-cs-grid-off]{visibility:hidden}

/* A whole group the chosen coverage does not apply to: it goes invisible and
   keeps its box, so the studio below it does not jump up under a thumb
   mid-scroll — §12. Written for Chip Size under Solid Color, which §5.2 has
   since removed from flake; what still uses it is the color group when a
   no-flake coverage is chosen and no solids pool resolved. */
.cs-group[data-cs-reserved]{visibility:hidden}

/* align-items:stretch is the grid default and is what keeps the cards in a row
   the same height once they carry descriptions of different lengths — Finish
   gained three at KAZ-749 Task 1. Stated rather than inherited, because a card
   row that silently ragged would read as broken. */
.cs-opts{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(196px,1fr));align-items:stretch}
.cs-opts > .cs-opt{height:100%}

/* ============ OPTION BUTTONS ============ */
/* Real <button>s — KAZ-746 §12. Selected state is carried by aria-pressed,
   which is also what the CSS keys off, so the visual and the accessible state
   are the same fact and cannot drift apart. */
.cs-opt{
  display:flex;flex-direction:column;gap:5px;align-items:flex-start;text-align:left;
  padding:16px 17px;border:1px solid var(--hair);border-radius:var(--r);
  background:rgba(26,26,26,.62);box-shadow:var(--edge);
  color:var(--offwhite);font:inherit;cursor:pointer;width:100%;
  transition:border-color .18s ease,background .18s ease,transform .18s ease;
}
.cs-opt:hover{border-color:rgba(245,243,239,.3);background:rgba(43,43,43,.7)}
.cs-opt:active{transform:translateY(1px)}
.cs-opt-n{
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:1.06rem;letter-spacing:.07em;text-transform:uppercase;line-height:1.2;
}
.cs-opt-d{font-size:.86rem;color:var(--silver);line-height:1.5}

.cs-opt[aria-pressed="true"]{
  border-color:var(--orange);background:rgba(255,106,0,.1);
  box-shadow:var(--edge),0 0 0 1px var(--orange) inset;
}
.cs-opt[aria-pressed="true"] .cs-opt-d{color:#C9CBCE}

/* Add-ons are multi-select. A checkbox glyph says so before it is pressed —
   the single-select groups have nothing in this corner. */
.cs-opt-multi{padding-left:46px;position:relative}
.cs-opt-multi::before{
  content:"";position:absolute;left:17px;top:18px;width:17px;height:17px;
  border:1px solid var(--silver);border-radius:3px;
}
.cs-opt-multi[aria-pressed="true"]::before{
  border-color:var(--orange);background:var(--orange);
}
.cs-opt-multi[aria-pressed="true"]::after{
  content:"";position:absolute;left:22px;top:21px;width:6px;height:10px;
  border:solid #FFF;border-width:0 2px 2px 0;transform:rotate(42deg);
}

.cs-opt:disabled{opacity:.55;cursor:not-allowed}
.cs-opt:disabled:hover{
  border-color:var(--hair);background:rgba(26,26,26,.62);
}
/* The inactive pool's controls are disabled as well as visibility:hidden
   (§5.1). Neutralise the hover affordances so nothing animates behind the
   hidden layer. */
.cs-tile:disabled,.cs-zoom:disabled{cursor:not-allowed}
.cs-tile:disabled:hover .cs-tile-sw{box-shadow:inset 0 0 0 1px rgba(0,0,0,.35);transform:none}
.cs-zoom:disabled:hover{background:rgba(15,15,15,.62);transform:none}

/* ============ SWATCH TILES — KAZ-750 §3 ============ */
/* Identical treatment for both pools. They share one grid cell (§5.1), so any
   difference in tile size between them would reintroduce the layout shift the
   swap was built to avoid. One set of rules, both grids. */

/* Column counts are sized against the OPTIONS COLUMN, not the viewport: from
   1024px up that column shares its width with the 330px sticky panel, so the
   space a tile gets is roughly 816px at desktop, not the full page. Measured
   tile edges: ~193px at 1440, ~190px at 1024, ~228px at 768, ~205px at 480,
   ~137px at 344. Counts are fixed per band rather than auto-fit so the two
   pools cannot disagree about how many columns they have. */
.cs-pool{display:grid;gap:26px;align-content:start}
.cs-tiles{display:grid;gap:14px;grid-template-columns:repeat(2,minmax(0,1fr))}

@media(min-width:480px){ .cs-tiles{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media(min-width:768px){ .cs-tiles{grid-template-columns:repeat(3,minmax(0,1fr))} }
/* 1024px is where the sticky panel takes 330px away, so the count drops back
   to 3 in a narrower column rather than rising. */
@media(min-width:1024px){ .cs-tiles{grid-template-columns:repeat(3,minmax(0,1fr))} }
@media(min-width:1400px){ .cs-tiles{grid-template-columns:repeat(4,minmax(0,1fr))} }

/* ---- family subheads (§4) ---- */
/* One step below .cs-gt: same face, smaller, and silver rather than the group
   label's weight, so the hierarchy reads group > family > tile. */
.cs-fam{
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:.82rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--midgray);margin:0 0 -12px;
}

/* ---- the tile ---- */
/* The wrapper exists so the zoom control can be a sibling of the select
   button rather than nested inside it. It carries the per-color custom
   properties, which inherit down to the swatch face. */
.cs-tile-wrap{position:relative;display:grid}
.cs-tile{
  display:grid;gap:9px;padding:0;border:0;background:none;
  font:inherit;color:var(--offwhite);cursor:pointer;width:100%;text-align:left;
}

/* Swatch fills the tile edge to edge — no card, no padding, no chrome. The
   square is what carries the selected border, so it is the positioned box. */
.cs-tile-sw{
  display:block;aspect-ratio:1/1;width:100%;
  border-radius:var(--r);overflow:hidden;position:relative;
  background:var(--charcoal);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.35);
  transition:box-shadow .16s ease,transform .16s ease;
}
.cs-tile-sw img{width:100%;height:100%;object-fit:cover;display:block}

/* Hover on an unselected tile: hairline in the utility gray, and a slight
   lift. Both are box-shadow/transform, so neither moves a neighbour. */
.cs-tile:hover .cs-tile-sw{
  box-shadow:inset 0 0 0 1px var(--silver),0 8px 20px rgba(0,0,0,.45);
  transform:translateY(-2px);
}

/* Selected: a 3px orange border drawn INSIDE the box, so selecting cannot
   resize a tile or reflow the grid, plus the check badge below. */
.cs-tile[aria-pressed="true"] .cs-tile-sw{
  box-shadow:inset 0 0 0 3px var(--orange);
}
.cs-tile[aria-pressed="true"]:hover .cs-tile-sw{
  box-shadow:inset 0 0 0 3px var(--orange),0 8px 20px rgba(0,0,0,.45);
}

.cs-tile-name{
  font-family:'Barlow Condensed',sans-serif;font-weight:500;
  font-size:.94rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--silver);line-height:1.25;
}
.cs-tile[aria-pressed="true"] .cs-tile-name{font-weight:700;color:var(--offwhite)}

/* The check badge, top-left, drawn in CSS: an orange disc with a white tick.
   Hidden until selected — it is the confirmation, not a hint. */
.cs-tile-check{
  position:absolute;top:10px;left:10px;width:22px;height:22px;border-radius:50%;
  background:var(--orange);opacity:0;transform:scale(.6);
  transition:opacity .14s ease,transform .14s ease;pointer-events:none;
}
.cs-tile-check::after{
  content:"";position:absolute;left:8px;top:4px;width:5px;height:10px;
  border:solid #FFF;border-width:0 2px 2px 0;transform:rotate(42deg);
}
.cs-tile[aria-pressed="true"] .cs-tile-check{opacity:1;transform:scale(1)}

/* ---- zoom affordance (§5) ---- */
/* Off-white on a semi-transparent dark disc, so it reads over Saltflat at one
   end of the catalog and Coalseam at the other without changing color. */
.cs-zoom{
  position:absolute;top:10px;right:10px;width:28px;height:28px;
  display:flex;align-items:center;justify-content:center;
  border:0;border-radius:50%;padding:0;cursor:pointer;
  background:rgba(15,15,15,.62);color:var(--offwhite);
  transition:background .16s ease,transform .16s ease;
}
.cs-zoom:hover{background:rgba(15,15,15,.85);transform:scale(1.08)}
.cs-zoom:focus-visible{outline:2px solid var(--orange);outline-offset:2px}

/* ============ ZOOM MODAL — KAZ-750 §5 ============ */
.cs-modal{
  position:fixed;inset:0;z-index:120;display:flex;
  align-items:center;justify-content:center;padding:24px;
}
.cs-modal[hidden]{display:none}
.cs-modal-scrim{position:absolute;inset:0;background:rgba(8,8,9,.86)}
.cs-modal-box{
  position:relative;z-index:1;width:min(520px,100%);max-height:100%;
  overflow:auto;background:var(--charcoal);border:1px solid var(--hair);
  border-radius:var(--r);box-shadow:var(--edge),var(--panel-shadow);padding:22px;
}
.cs-modal-sw{
  display:block;aspect-ratio:1/1;width:100%;border-radius:var(--r);
  overflow:hidden;background:var(--charcoal);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.35);
}
.cs-modal-sw img{width:100%;height:100%;object-fit:cover;display:block}
.cs-modal-n{
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:1.3rem;letter-spacing:.09em;text-transform:uppercase;
  color:var(--offwhite);margin:16px 0 0;
}
.cs-modal-d{color:var(--silver);font-size:.92rem;line-height:1.6;margin:8px 0 0}
.cs-modal-go{margin-top:18px;width:100%}
.cs-modal-x{
  position:absolute;top:10px;right:10px;width:34px;height:34px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(15,15,15,.62);color:var(--offwhite);
  border:0;border-radius:50%;cursor:pointer;font-size:1.2rem;line-height:1;
}
.cs-modal-x:hover{background:rgba(15,15,15,.9)}
.cs-modal-x:focus-visible,.cs-modal-go:focus-visible{outline:2px solid var(--orange);outline-offset:2px}

/* ============ SUMMARY ============ */
/* In flow, deliberately not fixed — see the note in includes/color-studio.php.
   .mbar is already fixed to the bottom of the viewport on phones. */
.cs-sum{
  border:1px solid var(--hair);border-radius:var(--r);
  background:rgba(43,43,43,.62);box-shadow:var(--edge);
  padding:20px 22px;display:grid;gap:8px;
}
.cs-sum-l{
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:.92rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--orange);margin:0;
}
.cs-sum-v{font-size:1.04rem;color:var(--offwhite);margin:0;line-height:1.55}
.cs-sum-reset{margin:0}
.cs-reset{
  background:none;border:0;padding:0;font:inherit;cursor:pointer;
  color:var(--silver);font-size:.86rem;text-decoration:underline;
  text-underline-offset:3px;
}
.cs-reset:hover{color:var(--offwhite)}
.cs-reset[hidden]{display:none}

/* The line that names what is still missing. Silver, not orange: it is
   guidance, not an alert, and §2's palette keeps orange for the CTA itself. */
.cs-sum-hint{margin:0;font-size:.92rem;color:var(--silver);line-height:1.5}
.cs-sum-hint[hidden]{display:none}

/* ============ CTA ============ */
/* .btn .btn-primary from style.css carries the brand's white-on-orange; only
   the states style.css has no opinion about are set here. Full width inside
   the panel, which is narrow by design at every breakpoint. */
.cs-sum-go{margin:4px 0 0}
.cs-cta{width:100%}
/* Disabled is the brand's utility gray at low opacity — no new color, and
   visibly not-yet-pressable rather than merely dimmed orange, which would read
   as a broken button. */
.cs-cta:disabled{
  background:rgba(168,170,174,.16);color:var(--silver);
  box-shadow:none;cursor:not-allowed;
}
.cs-cta:disabled:hover{background:rgba(168,170,174,.16)}
.cs-cta:disabled:active{transform:none}

/* ============ GENERATOR PREVIEW — KAZ-746 Phase 2 ============ */
/* A pigment tile is the pigment, flat. No speckle layers, no generated
   pattern: the pattern belongs to the preview. */
.cs-sw-pig{background-color:var(--base,#2b2b2b);background-image:none}
/* A look tile holds a canvas drawn by the generator. */
.cs-sw-gen{background:var(--deep)}
.cs-sw-gen canvas{width:100%;height:100%;display:block}

/* The stage. A FIXED aspect box: the canvas is sized to it and repainted
   inside it, so a re-render can change every pixel and move nothing — §12.
   3:2 because a floor is wider than it is deep in every photograph of one. */
.cs-preview{display:grid;gap:9px}
.cs-preview-box{
  position:relative;aspect-ratio:3/2;width:100%;
  border-radius:var(--r);overflow:hidden;
  background:var(--charcoal);box-shadow:inset 0 0 0 1px rgba(0,0,0,.35),var(--edge);
}
.cs-preview-box canvas{width:100%;height:100%;display:block}
/* Before a floor exists to draw. Occupies the same box, so the stage never
   changes size between empty and drawn. */
.cs-preview-empty{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  text-align:center;padding:18px;color:var(--silver);
  font-family:'Barlow Condensed',sans-serif;font-weight:600;
  font-size:.96rem;letter-spacing:.11em;text-transform:uppercase;
}
.cs-preview-empty[hidden]{display:none}
.cs-zoom-lg{width:34px;height:34px}
.cs-zoom-lg[hidden]{display:none}
.cs-preview-note{
  margin:0;font-size:.82rem;color:var(--midgray);line-height:1.5;
}

/* ============ STICKY PANEL — KAZ-749 Task 4 ============ */
/* At >=1024px the studio becomes two columns and the panel rides along beside
   the options instead of waiting at the bottom of them.
 *
 * position:sticky, never fixed, and only here: KAZ-746 §12.1 forbids a second
 * fixed element at any width where .mbar is visible. .mbar appears at <=640px
 * (style.css), so this rule and that bar can never be on screen together —
 * and a sticky grid item is confined to its own grid area regardless.
 *
 * top clears the sticky site header (position:sticky; top:0; z-index:60). */
/* Below the two-column breakpoint the side column stops being a column: its
   children become ordinary children of .cs again, and the preview takes the
   top of the studio. It leads rather than trails because a reader on a phone
   scrolls down through five groups — a preview at the bottom is a preview
   nobody sees while choosing. In flow, never fixed, at every width (§12.1).

   These are the narrow-screen defaults and they MUST stay above the >=1024px
   block: an unconditional rule that appears after a media query of the same
   specificity wins at every width, which silently cost the desktop layout its
   sticky wrapper the first time this was written. */
.cs-side{display:contents}
.cs-preview{order:-1}

@media(min-width:1024px){
  .cs{grid-template-columns:minmax(0,1fr) 330px;align-items:start}
  .cs-sum{position:sticky;top:112px}
  /* When a preview shares the column, ONE sticky wrapper carries both, so the
     stage and the summary travel together and cannot overlap each other. */
  .cs-side{display:grid;gap:22px;position:sticky;top:112px}
  .cs-side .cs-sum{position:static;top:auto}
  .cs-preview{order:0}
}

/* ============ DISCLAIMER + NOSCRIPT ============ */
/* KAZ-746 §2: nothing may imply a swatch depicts completed work. */
.cs-note{
  margin-top:26px;font-size:.84rem;color:var(--midgray);
  max-width:70ch;line-height:1.6;
}
.cs-ns{margin-top:26px}
.cs-ns p{color:var(--silver);font-size:.94rem;margin-top:10px;max-width:70ch}
.cs-ns strong{color:var(--offwhite)}
.cs-ns a{color:var(--orange);text-decoration:underline;text-underline-offset:3px}

/* ============ RESPONSIVE ============ */
/* Acceptance is 344px (folded Z Fold) and 768px with no horizontal scroll.
   The grids are auto-fit/minmax, so they reflow on their own down to the
   point where a single 196px column plus .wrap's 20px gutters exceeds the
   viewport — 236px — which is below any target width. These two steps tune
   the density rather than rescuing the layout. */
@media(max-width:768px){
  .cs{gap:32px}
  .cs-opts{grid-template-columns:repeat(auto-fit,minmax(168px,1fr))}
}
@media(max-width:420px){
  .cs-sec .sec-head{margin-bottom:30px}
  .cs-opts{grid-template-columns:1fr}
  .cs-tiles{gap:10px}
  .cs-opt{padding:14px 15px}
  .cs-opt-multi{padding-left:42px}
  .cs-opt-multi::before{left:15px}
  .cs-opt-multi[aria-pressed="true"]::after{left:20px}
  .cs-sum{padding:17px 18px}
}

/* ============ REDUCED MOTION ============ */
/* style.css already kills transitions globally under this query; repeated
   here because this sheet can load on its own and must not depend on the
   order the two arrive in. */
/* The generator paints; it never animates. There is no loop to disable here —
   the only motion in the studio is the tile hover and the check badge. */
@media(prefers-reduced-motion:reduce){
  .cs-opt,.cs-tile-sw,.cs-tile-check,.cs-zoom{transition:none}
  .cs-opt:active{transform:none}
  .cs-tile:hover .cs-tile-sw,.cs-zoom:hover{transform:none}
}
